我开发了一个包含MVC4,jQuery和Twitter Boostrap的网站。现在我决定在某些页面添加knockout,以使工作流程更流畅。在此特定页面上,目的是在左侧有一个项目列表,可以使用jQuery UI可排序项目重新排序。单击时,每个项目的详细信息将在右侧区域中进行编辑。根据类型的不同,编辑将会有很大差异,因此我决定根据类型设置单独的DIV标签。
之前的工作版本通过模型加载页面项。我的想法是在knockout viewmodel中添加一个observable数组,然后在页面加载时加载它。该模型在服务器上定义,因此我的目的是不再在客户端视图模型上定义所有属性。进一步的操作和编辑只会使用相同的集合,并通过AJAX调用将新的/更改/删除的值上传到服务器。
我已经阅读了淘汰演示并搜索了类似用例的stackoverflow。我想我遵循了这些建议,但显然缺少了一些东西。模型加载好了。项目出现并根据类型显示不同的颜色。它们是可排序的,并且随时可以将更改发送回服务器并保持正常。
缺少的部分是显示和编辑当前所选项目。我在viewmodel中添加了另一个名为currentItem的属性。在函数$(“body”)。on(“click”,“。sortableItem”中,我可以验证是否已加载currentItem并且Heading属性是否正确。
但DIV divEditType1的可见性和内容不受影响。我误解了绑定概念吗?我是否误解了服务器JSON数组的加载?任何帮助都非常感谢。
这是服务器页面模型:
public class PresentationItemsModel
{
public Guid PresentationId { get; set; }
public string DisplayName { get; set; }
public List<PresentationItemModel> PresentationItems { get; set; }
}
这是重复的项目模型:
public class PresentationItemModel
{
public Guid PresentationItemId { get; set; }
public string PresentationItemType { get; set; }
public int OrderNumber { get; set; }
public string Heading { get; set; }
public string Content { get; set; }
....
}
这是客户端页面(已删除不相关的部分):
@model MyCustomWeb.Models.PresentationItemsModel
<header>
<h2>@Model.DisplayName</h2>
</header>
<div style="float: left;">
<fieldset>
<legend>Current list</legend>
<ul id="sortable" data-bind="foreach: presentationItems">
<li class="sortableItem btn btn-block" data-bind="css: 'sortable' + PresentationItemType + 'Item'">
<div style="font-weight: 500;">
<span data-bind="text: Heading"></span>
<span class="ui-icon ui-icon-arrowthick-2-n-s" style="display: inline-block; color: gray; float: right; opacity: 0.5; height: 14px; margin: 2px 4px 0 0"></span>
</div>
</li>
</ul>
</fieldset>
</div>
<div id="divEditType1" data-bind="visible: currentItem.PresentationItemType == 'Type1'" style="float: left; margin-left: 50px;">
<fieldset>
<legend>Edit Type 1</legend>
<div class="control-group">
<input type="text" data-bind="value: currentItem.Heading" placeholder = "Enter Heading" />
</div>
<div class="control-group">
<button id="btnSave" type="submit" class="btn btn-primary">Save</button>
<button id="btnDelete" type="submit" class="btn btn-danger">Delete</button>
</div>
</fieldset>
</div>
<div id="divEditType2" data-bind="visible: currentItem.PresentationItemType = 'Type2'" style="float: left; margin-left: 50px;">
</div>
<div id="divEditType3" data-bind="visible: currentItem.PresentationItemType = 'Type3'" style="float: left; margin-left: 50px;">
</div>
@section Scripts {
<script>
$(document).ready(function () {
// Enable item sorting
$("#sortable").sortable(
{
cursor: "move",
placeholder: "sortableSeparator",
update: function () {
// Create array of all changed items
var changeItems = [];
var currentOrderNumber = 1;
$(".sortableItem").each(function () {
var id = $(this).attr('data-id');
var previousOrderNumber = $(this).attr('data-orderNumber');
if (currentOrderNumber != previousOrderNumber)
changeItems.push({ "id": id, "orderNumber": currentOrderNumber });
currentOrderNumber += 1;
});
// Send ajax action
$.ajax({
type: "PUT",
url: "/api/PresentationApi/ChangeOrder/" + "@Model.PresentationId",
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(changeItems)
});
},
}
);
// Enable change depending on item click
// Note: Must be done this way beacuse of the dynamic binding!
$("body").on("click", ".sortableItem", function () {
viewModel.currentItem = ko.dataFor(this);
alert(viewModel.currentItem.Heading); // Works fine!
//alert(JSON.stringify(viewModel.currentItem)); // Also looks good!
});
// Knockout view model
function ViewModel() {
var self = this;
self.presentationItems = ko.observableArray([]);
self.currentItem = ko.observable();
}
var viewModel = new ViewModel();
viewModel.presentationItems(@Html.Raw(Json.Encode(Model.PresentationItems)));
ko.applyBindings(viewModel);
});
</script>
}
编辑: 可以在此处找到创建小提琴演示的尝试: http://jsfiddle.net/XXNz9/
答案 0 :(得分:1)
我建议你用另一个div包装你的“divEditType1”。内部div的上下文将更改为“currentItem”,因此您不需要每次都写入
<div data-bind="with: currentItem">
<div id="divEditType1" data-bind="visible: PresentationItemType = 'Type1'" style="float: left; margin-left: 50px;">
<fieldset>
<legend>Edit Type 1</legend>
<div class="control-group">
<input type="text" data-bind="value: Heading" placeholder = "Enter Heading" />
</div>
<div class="control-group">
<button id="btnSave" type="submit" class="btn btn-primary">Save</button>
<button id="btnDelete" type="submit" class="btn btn-danger">Delete</button>
</div>
</fieldset>
</div>
</div>
这也可以解决您的问题,因为如果在应用currentItem == null时您的绑定可能会失败