网格堆栈在删除时未更新
Gridstack not updating on delete
这是我使用 Knockout 绑定的 Gridstack 布局示例。问题是我的观点没有在应该的时候根据模型进行更新。
按 Delete me
后,控制台输出显示widgets
可观察数组已正确更新,而视图未正确更新。原因似乎在这一行(未调用):
ko.utils.domNodeDisposal.addDisposeCallback(item, function () {
self.grid.removeWidget(item);
});
据我所知,foreach
绑定应该自动更新,为什么不更新?
var ViewModel = function() {
var self = this;
self.grid = null;
self.widgets = ko.observableArray([{
x: 0,
y: 0,
width: 1,
height: 1
}, {
x: 0,
y: 1,
width: 1,
height: 1
}]);
self.deleteWidget = function(item) {
console.log("widgets before", self.widgets());
self.widgets.remove(item);
console.log("widgets after", self.widgets());
return false;
};
self.afterAddWidget = function(items) {
if (self.grid == null) {
self.grid = $('.grid-stack').gridstack({
auto: false
}).data('gridstack');
}
var item = _.find(items, function(i) {
return i.nodeType == 1
});
self.grid.addWidget(item);
ko.utils.domNodeDisposal.addDisposeCallback(item, function() {
self.grid.removeWidget(item);
});
};
};
ko.applyBindings(new ViewModel());
.grid-stack {
background: lightgoldenrodyellow;
}
.grid-stack-item-content {
color: #2c3e50;
text-align: center;
background-color: #18bc9c;
}
<link rel="stylesheet" href="https://raw.githubusercontent.com/troolee/gridstack.js/master/dist/gridstack.css" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.0/jquery-ui.js" type="text/javascript"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.5.0/lodash.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js" type="text/javascript"></script>
<script type="text/javascript" src="https://rawgit.com/troolee/gridstack.js/master/dist/gridstack.js"></script>
<div class="grid-stack" data-bind="foreach: {data: widgets, afterRender: afterAddWidget}">
<div class="grid-stack-item" data-bind="attr: {'data-gs-x': $data.x, 'data-gs-y': $data.y, 'data-gs-width': $data.width, 'data-gs-height': $data.height, 'data-gs-auto-position': $data.auto_position}">
<div class="grid-stack-item-content">
<button data-bind="click: $root.deleteWidget">Delete me</button>
</div>
</div>
</div>
该问题实际上是由</div>
结束标记之间的额外空格字符引起的。该示例对此发出警告。就我而言,它是由代码格式化程序自动插入的,因此没有引起注意。HTML 模板中的行应</div></div><!-- <---- NO SPACE BETWEEN THESE CLOSING TAGS -->
,</div></div>
之间没有空格
var ViewModel = function() {
var self = this;
self.grid = null;
self.widgets = ko.observableArray([{
x: 0,
y: 0,
width: 1,
height: 1
}, {
x: 0,
y: 1,
width: 1,
height: 1
}]);
self.deleteWidget = function(item) {
console.log("widgets before", self.widgets());
self.widgets.remove(item);
console.log("widgets after", self.widgets());
return false;
};
self.afterAddWidget = function(items) {
if (self.grid == null) {
self.grid = $('.grid-stack').gridstack({
auto: false
}).data('gridstack');
}
var item = _.find(items, function(i) {
return i.nodeType == 1
});
self.grid.addWidget(item);
ko.utils.domNodeDisposal.addDisposeCallback(item, function() {
self.grid.removeWidget(item);
});
};
};
ko.applyBindings(new ViewModel());
.grid-stack {
background: lightgoldenrodyellow;
}
.grid-stack-item-content {
color: #2c3e50;
text-align: center;
background-color: #18bc9c;
}
<link rel="stylesheet" href="https://raw.githubusercontent.com/troolee/gridstack.js/master/dist/gridstack.css" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.0/jquery-ui.js" type="text/javascript"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.5.0/lodash.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js" type="text/javascript"></script>
<script type="text/javascript" src="https://rawgit.com/troolee/gridstack.js/master/dist/gridstack.js"></script>
<div class="grid-stack" data-bind="foreach: {data: widgets, afterRender: afterAddWidget}">
<div class="grid-stack-item" data-bind="attr: {'data-gs-x': $data.x, 'data-gs-y': $data.y, 'data-gs-width': $data.width, 'data-gs-height': $data.height, 'data-gs-auto-position': $data.auto_position}">
<div class="grid-stack-item-content">
<button data-bind="click: $root.deleteWidget">Delete me</button>
</div>
</div></div><!-- <---- NO SPACE BETWEEN THESE CLOSING TAGS -->
Gridstack 是一个控制 DOM 的小部件。你需要某种绑定处理程序来使 Knockout 与 DOM 控制小部件很好地发挥作用。
看起来您可能正在从此示例开始工作。它以一种类似于内置绑定处理程序的方式使用组件。它似乎有效,但我建议将 DOM 操作放在它所在的位置:在绑定处理程序中。
更新:下面是将 gridstack 代码放入绑定处理程序的示例。它只是包装一个foreach
绑定处理程序,并在更新中向其添加afterRender
选项。现在,视图模型看起来像一个视图模型,您将能够处理页面上的多个网格堆栈,而无需$(.grid-stack)
选择错误的网格堆栈。
ko.bindingHandlers.gridstack = {
init: function(element, valueAccessor, allBindingsAccessor, data, context) {
ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, data, context);
return {
controlsDescendantBindings: true
};
},
update: function(element, valueAccessor, allBindingsAccessor, data, context) {
var widgets = valueAccessor(),
grid = $(element).gridstack().data('gridstack'),
afterAddWidget = function(items) {
var item = _.find(items, function(i) {
return i.nodeType === 1;
});
grid.addWidget(item);
ko.utils.domNodeDisposal.addDisposeCallback(item, function() {
grid.removeWidget(item);
});
},
newVA = function() {
return {
data: widgets,
afterRender: afterAddWidget
};
};
ko.bindingHandlers.foreach.update(element, newVA, allBindingsAccessor, data, context);
}
};
var ViewModel = function() {
var self = this;
self.grid = null;
self.widgets = ko.observableArray([{
x: 0,
y: 0,
width: 1,
height: 1
}, {
x: 0,
y: 1,
width: 1,
height: 1
}]);
self.deleteWidget = function(item) {
self.widgets.remove(item);
};
};
ko.applyBindings(new ViewModel());
.grid-stack {
background: lightgoldenrodyellow;
}
.grid-stack-item-content {
color: #2c3e50;
text-align: center;
background-color: #18bc9c;
}
<link rel="stylesheet" href="https://raw.githubusercontent.com/troolee/gridstack.js/master/dist/gridstack.css" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.0/jquery-ui.js" type="text/javascript"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.5.0/lodash.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-debug.js" type="text/javascript"></script>
<script type="text/javascript" src="https://rawgit.com/troolee/gridstack.js/master/dist/gridstack.js"></script>
<div class="grid-stack" data-bind="gridstack: widgets">
<div class="grid-stack-item" data-bind="attr: {'data-gs-x': $data.x, 'data-gs-y': $data.y, 'data-gs-width': $data.width, 'data-gs-height': $data.height, 'data-gs-auto-position': $data.auto_position}">
<div class="grid-stack-item-content">
<button data-bind="click: $parent.deleteWidget">Delete me</button>
</div>
</div></div><!-- <---- NO SPACE BETWEEN THESE CLOSING TAGS -->
相关文章:
- Mongoose-在更新中删除数组元素
- 谷歌地图/Angular JS:地图更新并不总是反映数据,并且可以't删除标记
- Es6:能够在设置/更新/删除对象属性时调用自定义方法
- 手持:删除行后更新渲染器
- 拖动&删除Fullcalendar.io资源-更新视图
- 如何在使用Javascript删除某一行时更新表
- orderBy$filter在项目删除(拼接)后阻止ng重复列表更新
- 如何使用Extendscript scriptui插入、更新、删除XML元素的值
- 更新分组条形图(转换或删除元素组)
- Chrome扩展程序 - 页面更新两次,然后在YouTube上删除
- 对可观察数组foreach的更新删除了格式化knockoutjs
- ReactJS-这个状态中的数组在删除时被正确更新,但结果是't,直到以后的状态发生变化
- 从数组中删除值,用新的数组总数更新html或'$'如果没有总计
- php使用ajax生成html表,以应用用户操作,如删除、更新和编辑
- 正在更新/删除猫鼬对象属性
- 创建新对象失败,错误代码:没有找到用于更新/删除的对象
- 在数据库表更改/更新/删除时触发jQuery事件
- 在asp.net MVC 4 razor视图中更新删除后的记录号
- 如何处理Angular控制器中的错误从MongoDB数据库更新/删除在Express
- 如何在MongoDB嵌套数组中更新/删除多个索引