当使用这个 JSFiddle作为参考来构建具有可组织内容的网格时,我遇到了一个问题。一条错误消息说Error: viewModel is not defined
。
它通常应该像示例中那样工作,因为 myviewModel
是在 JS 的第一行定义的。它可能与viewModel
从模板中请求有关。
在检查其他答案时,它们都太笼统了。我没有找到一个能解决我问题的答案。
完整的错误:
Uncaught ReferenceError: Unable to process binding "template: function (){return { name:'gridTmpl',foreach:gridItems,templateOptions:{ parentList:gridItems}} }"
Message: Unable to process binding "template: function (){return { name:'rowTmpl',foreach:rowItems,templateOptions:{ parentList:rowItems}} }"
Message: Unable to process binding "visible: function (){return $data !== viewModel.selectedRowItem() }"
Message: viewModel is not defined
var viewModel = {
gridItems: ko.observableArray(
[{
"rowItems": [{
"name": "Item 1"
}, {
"name": "Item 2"
}, {
"name": "Item 3"
}]
}, {
"rowItems": [{
"name": "Item 4"
}]
}, {
"rowItems": [{
"name": "Item 5"
}, {
"name": "Item 6"
}]
}]
),
selectedRowItem: ko.observable(),
selectRowItem: function(rowItem) {
this.selectedRowItem(rowItem);
}
};
//connect items with observableArrays
ko.bindingHandlers.sortableList = {
init: function(element, valueAccessor, allBindingsAccessor, context) {
$(element).data("sortList", valueAccessor()); //attach meta-data
$(element).sortable({
update: function(event, ui) {
var item = ui.item.data("sortItem");
if (item) {
//identify parents
var originalParent = ui.item.data("parentList");
var newParent = ui.item.parent().data("sortList");
//figure out its new position
var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]);
if (position >= 0) {
originalParent.remove(item);
newParent.splice(position, 0, item);
}
ui.item.remove();
}
},
connectWith: '.container'
});
}
};
//attach meta-data
ko.bindingHandlers.sortableItem = {
init: function(element, valueAccessor) {
var options = valueAccessor();
$(element).data("sortItem", options.item);
$(element).data("parentList", options.parentList);
}
};
//control visibility, give element focus, and select the contents (in order)
ko.bindingHandlers.visibleAndSelect = {
update: function(element, valueAccessor) {
ko.bindingHandlers.visible.update(element, valueAccessor);
if (valueAccessor()) {
setTimeout(function() {
$(element).focus().select();
}, 0); //new RowItems are not in DOM yet
}
}
}
ko.applyBindings(viewModel);
.sortable {
list-style-type: none;
margin: 0;
padding: 0;
width: 60%;
}
.sortable li {
margin: 0 3px 3px 3px;
padding: 0.4em;
padding-left: 1.5em;
font-size: 1.4em;
height: 18px;
cursor: move;
}
.sortable li span {
position: absolute;
margin-left: -1.3em;
}
.sortable li.fixed {
cursor: default;
color: #959595;
opacity: 0.5;
}
.sortable-grid {
width: 100% !important;
}
.sortable-row {
height: 100% !important;
padding: 0 !important;
margin: 0 !important;
display: block !important;
}
.sortable-item {
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://code.jquery.com/ui/1.12.0-beta.1/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul class="sortable sortable-grid" data-bind="template: { name: 'gridTmpl', foreach: gridItems, templateOptions: { parentList: gridItems} }, sortableList: gridItems">
</ul>
<script id="gridTmpl" type="text/html">
<li class="sortable-row">
<table style="width:100%">
<tbody>
<tr class="sortable container" data-bind="template: { name: 'rowTmpl', foreach: rowItems, templateOptions: { parentList: rowItems} }, sortableList: rowItems">
</tr>
</tbody>
</table>
</li>
</script>
<script id="rowTmpl" type="text/html">
<td class="item" data-bind="sortableItem: { item: $data, parentList: $item.parentList }">
<a href="#" data-bind="text: name, click: function() { viewModel.selectRowItem($data); }, visible: $data !== viewModel.selectedRowItem()"></a>
<input data-bind="value: name, visibleAndSelect: $data === viewModel.selectedRowItem()" />
</td>
</script>