带有网格和挖空的小部件绑定
Widget binding with Gridster and Knockout
我是Javascript的新手,并尝试将Gridster与Knockout一起使用。 我有一个包含项目的数据库,我使用 KNOCKOUT foreach 将它们绑定到 UL。 UL 采用 Gridster 库的样式。 一切都很好,除非我尝试通过视图模型中的可观察数组向 UL 添加其他元素。
谁能帮我了解这里的操作范围和顺序? 感觉就像 Gridster 库没有对新小部件进行样式设置。
此 jsfiddle 显示了该问题的工作演示。 请注意,当您双击小部件时,它会创建一个新小部件,但不会将其放置在网格中。 相反,它只是在后面闲逛。
这是 HTML
<div class="gridster">
<ul data-bind="foreach: myData">
<li data-bind="attr:{
'data-row':datarow,
'data-col':datacol,
'data-sizex':datasizex,
'data-sizey':datasizey
},text:text, doubleClick: $parent.AddOne"></li>
</ul>
</div>
这是Javascript
//This is some widget data to start the process
var gridData = [ {text:'Widget #1', datarow:1, datacol:1, datasizex:1, datasizey:1},
{text:'Widget #2', datarow:2, datacol:1, datasizex:1, datasizey:1},
{text:'Widget #3', datarow:1, datacol:2, datasizex:1, datasizey:1},
{text:'Widget #4', datarow:2, datacol:2, datasizex:1, datasizey:1}];
// The viewmodel contains an observable array of widget data to be
// displayed on the gridster
var viewmodel = function () {
var self = this;
self.myData = ko.observableArray(gridData);
//AddOne adds an element to the observable array
// (called at runtime from doubleClick events)
self.AddOne = function () {
var self = this;
myViewModel.myData.push({
text: 'Widget Added After!',
datarow: 1,
datacol: 1,
datasizex: 1,
datasizey: 1
});
};
};
var myViewModel = new viewmodel();
ko.applyBindings(myViewModel);
$(".gridster ul").gridster({
widget_margins: [5, 5],
widget_base_dimensions: [140, 140]
});
这是 JSfiddle 中的完整示例。在这里,我只强调了删除功能
self.deleteOne = function (item) { console.log(item); var widget = $("#" + item.id); console.log(widget); var column = widget.attr("data-col"); if (column) { console.log('Removing '); // if this is commented out then the widgets won't re-arrange self.gridster.remove_widget(widget, function(){ self.myData.remove(item); console.log('Tiles: '+self.myData().length); }); } };
从可观察数组中删除元素的工作是在remove_widget回调中完成的。请参阅网格员的文档。因此,在删除小部件之前执行的 removeGridster 挂钩不再需要执行实际的remove_widget调用。
这是一个我认为更符合 MVVM 模式的工作解决方案:
http://jsfiddle.net/Be4cf/4/
//This is some widget data to start the process
var gridData = [
{id: "1", text:'Widget #1', datarow:1, datacol:1, datasizex:1, datasizey:1},
{id: "2", text:'Widget #2', datarow:1, datacol:2, datasizex:2, datasizey:1},
{id: "3", text:'Widget #3', datarow:1, datacol:4, datasizex:1, datasizey:1},
{id: "4", text:'Widget #4', datarow:2, datacol:1, datasizex:1, datasizey:2}];
// The viewmodel contains an observable array of widget data to be
// displayed on the gridster
var viewmodel = function () {
var self = this;
self.myData = ko.observableArray(gridData);
self.nextId = 5;
self.gridster = undefined;
// AddOne adds an element to the observable array.
// Notice how I'm not adding the element to gridster by hand here. This means
// that whatever the source of the add is (click, callback, web sockets event),
// the element will be added to gridster.
self.addOne = function () {
myViewModel.myData.push({
text: 'Widget Added After!',
datarow: 1,
datacol: 1,
datasizex: 1,
datasizey: 1,
id: self.nextId++
});
};
// Called after the render of the initial list.
// Gridster will add the existing widgets to its internal model.
self.initializeGridster = function() {
self.gridster = $(".gridster ul").gridster({
widget_margins: [5, 5],
widget_base_dimensions: [140, 140]
}).data('gridster');
};
// Called after the render of the new element.
self.addGridster = function(data, object) {
// This bypasses the add if gridster has not been initialized.
if (self.gridster) {
var $item = $(data[0].parentNode);
// The first afterRender event is fired 2 times. It appears to be a bug in knockout.
// I'm pretty new to knockout myself, so it might be a feature too! :)
// This skips the second call from the initial fired event.
if (!$item.hasClass("gs-w"))
{
// This removes the binding from the new node, since gridster will re-add the element.
ko.cleanNode(data[0].parentNode);
// Adds the widget to gridster.
self.gridster.add_widget($item);
// We must update the model with the position determined by gridster
object.datarow = parseInt($item.attr("data-row"));
object.datacol = parseInt($item.attr("data-col"));
}
}
};
};
var myViewModel = new viewmodel();
ko.applyBindings(myViewModel);
我仍然需要考虑删除和移动事件(在 gridster 中的移动应该更新视图模型中项目的 x 和 y 值)。我昨天开始使用淘汰赛,所以任何帮助将不胜感激。
我找不到最新版本的网格的 cdn。JSFiddle 指向我在 Azure 中添加的一个临时网站,我会把它保留几天,但请随时使用你自己的链接更新它。
/------------------------------更新----------------------------------/
我已经更新了我的代码以支持删除和移动小部件 (http://jsfiddle.net/Be4cf/11/),但有一个小警告:有一个悬而未决的问题 (https://github.com/knockout/knockout/issues/1130),即在调用 beforeRemove 事件之前,挖空会清除 jquery 数据。这会导致 gridster 崩溃,因为移动其他项所需的数据保存在数据元素中。解决方法可能是保留数据的副本并在以后将其重新添加到元素中,但我选择了懒惰的方式并在 KNOCKOUT 中注释了违规行。
将class="gs_w"添加到网格中的li应该可以工作
你应该做如下的事情。 addNewGridElement
被调用 - 渲染的 DOM 元素在 Gridster 的情况下很重要,因为gridster.add_widget
接受 DOM 元素作为其第一个参数 - 一旦你向 Knockout 可观察量添加了一些东西。在此之后,只需将domNode
添加到 Gridster 即可。
查看.html:
<div class="gridster">
<ul data-bind="foreach: { myData, afterAdd: $root.addNewGridElement }">
<li data-bind="attr:{
'data-row':datarow,
'data-col':datacol,
'data-sizex':datasizex,
'data-sizey':datasizey
},text:text, doubleClick: $parent.AddOne"></li>
</ul>
</div>
查看.js:
self.addNewGridElement = function (domNode, index, newTile) {
// Filter non li items - this will remove comments etc. dom nodes.
var liItem = $(domNode).filter('li');
if ( liItem.length > 0 ) {
// Add new Widget to Gridster
self.gridster.add_widget(domNode, newTile.x, newTile.y, newTile.row, newTile.col);
}
};
- 在VanillaJS中模拟模型双向数据绑定
- 无法通过数组映射绑定
- 主干-不管怎样,检查事件以前是否绑定过
- 用于搜索的聚合物嵌套绑定
- Angular:更新一次性绑定的数据
- 如何使用ngrepeat和双向绑定获得指令的隔离范围
- react.js中的密钥绑定
- 使用regex的jquery keydown绑定不会验证撇号和句点
- 将事件处理程序绑定到任何可能的事件
- AngularJS指令只识别双向绑定类型
- Dojo将索引0处的数据从数组绑定到小部件
- AngularJS绑定模型以选择更新输入数字字段,最小值为最大值
- 带有网格和挖空的小部件绑定
- KnockoutJS双绑定小部件应用程序
- 使用Knockout绑定jQuery Mobile窗口小部件的属性
- 将实数值绑定到Grails域属性(由Dojo小部件发送的值)
- 如何在同一个browserify命令中对文件进行最小化和因子绑定
- Angular ng-repeat works..但是没有值被绑定/显示(小枝)
- 为什么不调用绑定到<小程序>的“加载”事件处理程序
- 如何将JQuery UI可排序小部件绑定到通过Ajax加载的html