我正在尝试在使用Knockout.js的项目中创建一个可拖动的列表项。
我正在使用下面的代码,正如您所看到的那样非常简单:
<div id="room-view" >
<ul data-bind="foreach: rooms">
<li data-bind="text: name" class="draggable room-shape"></li>
</ul>
</div>
<script type="text/javascript">
$(function() {
$( ".draggable" ).draggable();
});
</script>
'room'列表渲染得很好,但没有一个项目是可拖动的。但是,如果我将'draggable'类应用于页面上的任何其他元素 - 它将变为可拖动。即使它们是其他列表项。唯一的区别是这些列表项是通过'foreach'绑定创建的。
有人能发现可能导致其无法正常运作的原因吗?
答案 0 :(得分:23)
foreach
的工作原理是,只要需要渲染项目,就可以保存要用作“模板”的元素副本。因此,您可拖动的元素不是由foreach
呈现的元素。
您可以尝试确保在draggable
之后调用applyBindings
,但这只有在您的rooms
不是更改的observableArray时才会生效。呈现的任何新项目都不可拖动。
另一种选择是使用afterRender选项在元素上调用draggable
。
更好的方法是使用自定义绑定。它可以很简单:
ko.bindingHandlers.draggable = {
init: function(element) {
$(element).draggable();
}
};
或者你可以根据你的项目被丢弃的位置实际更新observableArray,以获得更好的效果。
我一段时间写了一篇文章here。使用Knockout 2.0,我进行了一些更改以简化绑定,以便您可以在父级上使用sortableList
。
以下是可排序的示例:http://jsfiddle.net/rniemeyer/DVRVQ/
以下是列表之间删除的示例:http://jsfiddle.net/rniemeyer/sBHaP/
答案 1 :(得分:7)
问题是,当现有元素上的文档准备就绪时,会应用draggable()
。 Knockout.js将修改HTML并在开始时以及更新rooms
数组时创建新元素。
您需要的是每次呈现room-view
时启用拖动。您可以使用afterRender
。
试试这个:
<div id="room-view" >
<ul data-bind="foreach: { data: rooms, afterRender: afterRender }">
<li data-bind="text: name" class="draggable room-shape"></li>
</ul>
</div>
<script type="text/javascript">
// this is your already existing view-model that contains rooms, etc
function roomsViewModel() {
// ...
// insert this in your view-model
this.afterRender = function() {
$( ".draggable" ).draggable();
}
}
ko.applyBindings(new roomsViewModel());
</script>