使用knockout js我正在尝试创建一个具有4个和4个coulmns的表。下面是我的数组,它将有16个元素需要放在表格中。
/*----------------------------------------------------------------------*/
/* View Model */
/*----------------------------------------------------------------------*/
function ViewModel() {
var self = this;
self.items = ko.observableArray(["1.jpg",
"2.jpg",
"3.jpg",
"4.jpg",
"5.jpg",
"6.jpg"
]);
self.itemRows = ko.computed(function () { //computes the rows dynamically based on items
var rows = [];
var count = 0;
var items = self.items(); //get the item array
var current = [];
for(var i in items)
{
var item = items[i];
current.push(item);
count++;
if (count == 4)
{
count = 0;
rows.push(current);
current = []; //next array
}
}
if (current.length > 0)
{
rows.push(current);
}
return rows;
});
self.bindSort = function() {
var startIndex = -1;
var sortableSetup = {
start: function (event, ui)
{
startIndex = ui.item.index();
},
stop: function (event, ui)
{
var newIndex = ui.item.index();
if (startIndex > -1)
{
self.from = ko.observable(startIndex);
self.to = ko.observable(newIndex);
var iTo = parseInt(self.to());
var iFrom = parseInt(self.from());
var from = self.items()[iFrom];
var to = self.items()[iTo];
self.items()[iTo] = from;
self.items()[iFrom] = to;
//alert('before');
// alert(from);
// alert(to);
var fromA = self.items()[iFrom];
var toA = self.items()[iTo];
//alert('after');
//alert(fromA);
// alert(toA);
self.items.remove(from);
self.items.splice(newIndex, 0, toA);
self.items.remove(to);
self.items.splice(startIndex, 0, fromA);
//ui.item.remove();
self.items.valueHasMutated();
}
}
};
$(".fruitList").sortable( sortableSetup );
};
}
/*----------------------------------------------------------------------*/
/* KO HTML Binding */
/*----------------------------------------------------------------------*/
$(document).ready(function() {
// create the view model
var model = new ViewModel();
// call the bind method for jquery UI setup
model.bindSort();
// binds ko attributes with the html
ko.applyBindings(model);
});
并尝试在html中执行此操作,
<table data-bind="foreach: itemRows">
<tr class="fruitList" data-bind="foreach: $data">
<td><img data-bind="attr: { src: $data }" /></td>
</tr>
</table>
我无法获得数组的长度以及如何在第一次创建4个tds然后创建第二行时打破循环..任何建议???
更新
当我使用sortable时,下面的代码似乎不起作用,
start: function (event, ui)
{
startIndex = ui.item.index();
},
stop: function (event, ui)
{
var newIndex = ui.item.index();
答案 0 :(得分:2)
更新:移至可排序版本的底部
不可排序的版本
在编辑和提及排序之前,我创建了一个似乎符合您要求的jsfiddle:http://jsfiddle.net/fENSD/4/
我所做的是创建一个计算的observable,它观察你的项目是否可观察,并返回一个嵌套数组,其形状是你想要表格渲染的形状。这不是最有效的功能,但是通过一些工作,你可以减少分配的数组的数量(此时,每次更新时将为4x4网格创建5个左右):
self.items = ko.observableArray(["images/1.jpg", "images/2.jpg", "images/3.jpg", "images/4.jpg", "images/5.jpg", "images/6.jpg"]);
self.itemRows = ko.computed(function () { //computes the rows dynamically based on items
var rows = [];
var count = 0;
var items = self.items(); //get the item array
var current = [];
for(var i in items)
{
var item = items[i];
current.push(item);
count++;
if (count == 4)
{
count = 0;
rows.push(current);
current = []; //next array
}
}
if (current.length > 0)
{
rows.push(current);
}
return rows;
});
然后表格呈现如下:
<table data-bind="foreach: itemRows">
<tr data-bind="foreach: $data">
<td><img data-bind="attr: { src: $data }" /></td>
</tr>
</table>
JSFiddle包含一个向可观察项目添加项目的示例,以及正在更新的表格,以便反映出您是否希望在行动中看到该项目。在JSFiddle中还有一个示例,您可以通过一种方式获取items数组的长度(data-bind="text: items().length"
)。
可排序版本
这是一个相当大的变化,但我设法让排序工作。以jquery ui网站为例,我得到了以下内容:
对表进行排序非常困难,因此jquery ui示例实际上使用了一个列表,该列表具有定义的宽度,每个元素占用一定的宽度。这有效地创建了一个表。我假设你使用的图像可以使它们的大小完全相同。
要做到这一点,我有一些像这样的CSS:
#items { list-style-type: none; margin: 0; padding: 0; width: 200px; }
#items li { width: 48px; margin: 0px; padding: 0px; float: left; text-align: center; height: 48px; }
然后我创建了一个适当的绑定处理程序,如下所示:
ko.bindingHandlers['sortable'] = {
init: function (element, valueAccessor) {
var $element = $(element);
var observable = valueAccessor();
var value = ko.utils.unwrapObservable(observable);
$element.sortable({
stop: function(event, ui) {
var prev = ui.item.prev();
var data = ko.dataFor(ui.item[0]);
var index = 0;
if (prev.length > 0) {
//not the first item
var prevData = ko.dataFor(prev[0]);
var index = value.indexOf(prevData) + 1;
}
var oldIndex = value.indexOf(data);
value.splice(oldIndex, 1);
value.splice(index, 0, data);
observable.valueHasMutated();
}
});
}
};
每当更新sortable时,它都会修改传递给绑定的可观察数组。 注意:这是非常不可靠的,需要检查以确保传递的值实际上是一个可观察的值,然后再告诉它其值已经发生变异。
viewmodel看起来像这样:
function ViewModel() {
var self = this;
self.items = ko.observableArray(["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13"]);
self.items.subscribe(function (value) {
console.log(value); //this is so you can see that the array is indeed being re-sorted
});
self.add = function () {
self.items.push("another thing");
};
}
并呈现:
<ul id="items" data-bind="sortable: items, foreach: items">
<li><img data-bind="attr: { src: $data }" /></li>
</ul>
此方法的局限性在于,如果您的项目大小不同,则可排序的顺序与内存中实际表示的顺序略有不同。但是,假设您的所有元素大小相同,它应该可以正常工作。另一个问题是,这对重复项目不起作用。但是,要解决这个问题,应该是将每个元素作为包含值(甚至可以是可观察值)的对象而不是普通旧字符串的简单问题。