我正在尝试创建一种简单的方法来定义组列表。这些组包括id,描述,启用/禁用字段和排序顺序。我正在尝试使用KendoUI可排序小部件。我遇到的问题是:
该项目将从可观察数组中删除,但仍会显示在可排序的小部件中。
我试图尽可能地简化代码以证明问题。
//--------------------------------------------------------------------------------------------------
// MenuGroup View Models
//--------------------------------------------------------------------------------------------------
function MenuGroup() {
var self = this;
self.MenuGroupId = ko.observable(0);
self.Description = ko.observable("");
self.DisplayOrder = ko.observable(0);
self.MenuActive = ko.observable(true);
}
var menuGroupMapping = {
MenuGroup: {
key: function(group) {
return ko.utils.unwrapObservable(group.MenuGroupId);
},
create: function(group) {
var groupObj = ko.mapping.fromJS(group);
return groupObj;
}
}
}
function MenuGroupsViewModel() {
var self = this;
self.baseUri = "/api/menugroups";
self.menugroups = ko.observableArray();
self.newMenuGroup = ko.observable(new MenuGroup());
self.selectedGroup = ko.observable(new MenuGroup());
self.save = function(formElement) {
self.newMenuGroup().DisplayOrder(self.menugroups().length);
self.menugroups.push(self.newMenuGroup());
var g = new MenuGroup();
self.newMenuGroup(g);
};
self.deleteGroup = function(group) {
bootbox.confirm("Are you sure you want to delete the following menu group: " + group.Description(), function(result) {
self.menugroups.remove(group);
});
}
self.selectGroup = function(group) {
self.selectedGroup(group);
};
self.changeOrder = function(oldPosition, newPosition) {
var movedGroup = self.menugroups()[oldPosition];
movedGroup.DisplayOrder(newPosition);
var id = movedGroup.MenuGroupId();
ko.utils.arrayForEach(self.menugroups(), function(menugroup) {
if (oldPosition < newPosition) {
if (oldPosition <= menugroup.DisplayOrder() && newPosition >= menugroup.DisplayOrder() && menugroup.MenuGroupId() != id) {
menugroup.DisplayOrder(menugroup.DisplayOrder() - 1);
}
} else {
if (oldPosition >= menugroup.DisplayOrder() && newPosition <= menugroup.DisplayOrder() && menugroup.MenuGroupId() != id) {
menugroup.DisplayOrder(menugroup.DisplayOrder() + 1);
}
}
});
self.menugroups().splice(oldPosition, 1);
self.menugroups().splice(newPosition, 0, movedGroup);
}
var data = [{
"MenuGroupId": 0,
"Description": "Group A",
"DisplayOrder": 0,
"MenuActive": true
}, {
"MenuGroupId": 1,
"Description": "Group B",
"DisplayOrder": 1,
"MenuActive": false
}, {
"MenuGroupId": 2,
"Description": "Group C",
"DisplayOrder": 2,
"MenuActive": true
}, {
"MenuGroupId": 3,
"Description": "Group D",
"DisplayOrder": 3,
"MenuActive": true
}]
ko.mapping.fromJS(data, menuGroupMapping, self.menugroups);
}
//--------------------------------------------------------------------------------------------------
// Custom Bindings
//--------------------------------------------------------------------------------------------------
ko.bindingHandlers.showModal = {
init: function(element, valueAccessor) {},
update: function(element, valueAccessor) {
var value = valueAccessor();
if (ko.utils.unwrapObservable(value)) {
$(element).modal('show');
$("input", element).focus();
} else {
$(element).modal('hide');
}
}
}
mg = new MenuGroupsViewModel();
ko.applyBindings(mg, document.getElementById('menu-group-panel'));
$(document).ready(function() {
$("#menu-list").kendoSortable({
handler: ".menu-group-handle",
hint: function(element) {
return element.clone().addClass("hint");
},
placeholder: function(element) {
return element.clone().css({
"opacity": 0.3,
"border": "1px dashed #000000"
});
},
axis: "y",
container: "#menu-list",
cursor: "move",
change: onChange
});
});
function onChange(e) {
mg.changeOrder(e.oldIndex, e.newIndex);
}
&#13;
body {
padding: 20px;
}
.def-panel {
height: 100%;
margin: 0 30px 0 0;
width: 300px;
float: left;
}
#menu-list {
padding: 0;
width: 200px;
}
.menu-group-handle {
width: 30px;
height: 50px;
display: inline-block;
background-color: darkslategray;
}
div.menu-group {
display: inline-block;
width: 200px;
height: 50px;
background-color: aliceblue;
font-family: "Segoe Ui", Helvetica, Arial, 'DejaVu Sans', 'Liberation Sans', Freesans, sans-serif;
margin: 5px 0;
padding: 0;
cursor: pointer;
}
.menu-group-desc {
font-weight: 700;
margin: 10px;
}
.menu-group-selected {
background-color: darkslateblue !important;
color: white;
}
&#13;
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="//code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="//cdn.kendostatic.com/2014.2.903/js/kendo.all.min.js"></script>
<h2>Group/Item Definitions</h2>
<div id="menu-canvas">
<div id="menu-group-panel" class="def-panel">
<h3>Menu Groups</h3>
<div id="menu-list" data-bind="foreach: menugroups">
<div class="menu-group" data-bind="click: function() { mg.selectGroup($data) }, css: {'menu-group-selected': $parent.selectedGroup().MenuGroupId === $data.MenuGroupId}">
<span class=" menu-group-handle">
</span>
<!--<span data-bind="click: function() { mg.selectGroup($data) }, css: {'menu-group-selected': $parent.selectedGroup().MenuGroupId === $data.MenuGroupId}" class="menu-group">
-->
<span class="menu-group">
<button class="close menu-group-delete" data-bind="click: function() { mg.deleteGroup($data) } ">×</button>
<span class="menu-group-desc" data-bind="text: $data.Description"></span>
<span data-bind="text: $data.DisplayOrder"></span>
</span>
</div>
</div>
<div class="menu-list">
<button data-toggle="modal" data-target="#new-menu-group">New menu group...</button>
</div>
<div style="width: 800px;" data-bind="foreach: menugroups">
<span data-bind="text: $data.DisplayOrder"></span>-<span data-bind="text: $data.Description"></span>,
</div>
<div class="modal fade" data-bind="with: newMenuGroup" id="new-menu-group">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button class="close" data-dismiss="modal">×</button>
<h3>New Menu Group</h3>
</div>
<div class="modal-body">
<form class="form-horizontal" id="add-menugroup" data-bind="submit: $parent.save">
<fieldset>
<div class="form-group">
<label class="control-label col-sm-2">Group Name</label>
<div class="col-sm-10">
<input class="form-control" data-bind="value: Description" type="text" id="menu-group-name" />
</div>
</div>
<div class="form-group">
<div class="col-sm-10 col-sm-push-2">
<div class="checkbox">
<input data-bind="checked: MenuActive" type="checkbox" />
<label>Menu group is active</label>
</div>
</div>
</div>
</fieldset>
</form>
</div>
<div class="modal-footer">
<a href="#" class="btn btn-primary" data-bind="click: $parent.save" data-dismiss="modal">Save Changes</a>
<a href="#" class="btn" data-dismiss="modal">Close</a>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="//ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.debug.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.3.0/bootbox.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/jquery.ui/1.10.4/jquery-ui.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
&#13;
答案 0 :(得分:0)
将以下代码添加到MenuGroupsViewModel:
self.refresh = function () {
var tempArray = self.menugroups().slice(0);
self.menugroups([]);
self.menugroups(tempArray);
};
然后在self.deleteGroup函数中添加函数末尾的以下行:
self.refresh();
这会强制observableArray刷新。