KnockoutJS和多个嵌套模型
KnockoutJS and multiple nested models
我想找到一些教程如何创建一个嵌套的视图模型与两个以上的水平,例如:
-
- 为
-
-
- <
- 订单行/gh>
-
-
- 为
-
-
- <
- 订单行/gh>
-
-
-
- <
- 订单行/gh>
-
-
- 为
-
-
- <
- 订单行/gh>
-
列出了商店的所有订单,当我单击一个订单时,我应该看到能够编辑和删除订单行的订单行。通过一些教程,我已经得到了这个工作,但它搞砸了,我希望重新开始(最后我开始使用jQuery来得到我想要的,但感觉像是作弊和做了一半的事情)。有任何教程在那里,这或任何指针在哪里我应该开始(KnockoutJS或其他框架?是的,我已经遵循了knockoutjs.com上的教程,但被第三个级别的功能卡住了。
提前感谢。
编辑:遵循这个http://jsfiddle.net/peterf/8FMPc/light/
JS(简体)
// required by sharepoint
ExecuteOrDelayUntilScriptLoaded(loadTeams, "sp.js");
ko.observable.fn.beginEdit = function (transaction) {
var self = this;
var commitSubscription, rollbackSubscription;
if (self.slice) {
self.editValue = ko.observableArray(self.slice());
}
else {
self.editValue = ko.observable(self());
}
self.dispose = function () {
commitSubscription.dispose();
rollbackSubscription.dispose();
};
self.commit = function () {
self(self.editValue());
self.dispose();
};
self.rollback = function () {
self.editValue(self());
self.dispose();
};
commitSubscription = transaction.subscribe(self.commit, self, "commit");
rollbackSubscription = transaction.subscribe(self.rollback, self, "rollback");
return self;
}
function TeamModel (){
var self = this;
self.Team = function(title, members) {
this.title = title;
this.members = members;
}
self.editingItem = ko.observable();
self.editTransaction = new ko.subscribable();
self.isItemEditing = function(task) {
return task == self.editingItem();
};
self.editTask = function (task) {
if (self.editingItem() == null) {
task.beginEdit(self.editTransaction);
self.editingItem(task);
}
};
self.removeTask = function (task) {
if (self.editingItem() == null) {
var answer = confirm('Are you sure you want to delete this task? ' + task.title());
if (answer) {
// SharePoint client object model to delete task
}
}
};
self.applyTask = function (task) {
self.editTransaction.notifySubscribers(null, "commit");
// SharePoint client object model to update task
// hides the edit fields
self.editingItem(null);
};
self.cancelEdit = function (task) {
self.editTransaction.notifySubscribers(null, "rollback");
self.editingItem(null);
};
self.Member = function(name, id) {
this.name = name;
this.Tasks = ko.observableArray([]);
this.Task = function(id, title, priority, userComment, managerComment) {
this.id = ko.observable(id);
this.title = ko.observable(title);
this.priority = ko.observable(priority);
this.userComment = ko.observable(userComment);
this.managerComment = ko.observable(managerComment);
this.beginEdit = function(transaction) {
//this.title.beginEdit(transaction);
//this.userComment.beginEdit(transaction);
}
}
this.id = id;
this.retrieveTasks = function() {
if(this.Tasks().length === 0) {
// First click, expand
// SharePoint client object model to get tasks
} else {
// Collapse
//this.Tasks.removeAll();
}
}
}
self.Teams = ko.observableArray([]);
self.retrieveTeams = function() {
// SharePoint client object model to get a list of teams and their members
self.Teams.push(new self.Team(oListItem.get_item('Title'), members));
}
}
function loadTeams() {
var VM = new TeamModel();
VM.retrieveTeams();
VM.availableRankings = ["1","2","3","4","5","6","7","8","9","10"]
ko.applyBindings(VM);
}
HTML<div id="Workload" data-bind="visible: Teams().length>0">
<div data-bind="foreach: Teams" class="teams">
<div >
<h3 data-bind="text: title"></h3>
<div data-bind="foreach: members">
<div class="member">
<div data-bind="click: retrieveTasks">
<span data-bind="text: name" class="name"></span>
</div>
<table class="tasks" data-bind="visible: Tasks().length>0">
<tr>
<td class="title">Title</td>
<td class="priority">Priority</td>
<td class="user-comment">User Comment</td>
<td class="manager-comment">Manager Comment</td>
</tr>
<tbody data-bind="foreach: Tasks">
<tr class="row">
<td class="rowItem">
<input type="text" class="edit" data-bind="value: title, visible: $root.isItemEditing($data)"/>
<label class="read" data-bind="text: title, visible: !$root.isItemEditing($data)"/>
</td>
<td class="rowItem">
<select class="edit priority" data-bind="options: $root.availableRankings, value: priority, visible: $root.isItemEditing($data)"></select>
<label class="read" data-bind="text: priority, visible: !$root.isItemEditing($data)" />
</td>
<td class="rowItem">
<textarea rows="3" cols="25" class="edit userComment" data-bind="value: userComment, visible: $root.isItemEditing($data)"></textarea>
<label class="read" data-bind="text: userComment, visible: !$root.isItemEditing($data)"/>
</td>
<td class="rowItem">
<textarea rows="3" cols="25" class="edit managerComment" data-bind="value: managerComment, visible: $root.isItemEditing($data)"></textarea>
<label class="read" data-bind="text: managerComment, visible: !$root.isItemEditing($data)"/>
</td>
<td class="tools">
<a class="button toolButton" href="#" data-bind="click: $root.editTask.bind($root), visible: !$root.isItemEditing($data)">
Edit</a>
<Sharepoint:SPSecurityTrimmedControl runat="server" Permissions="DeleteListItems">
<a class="button toolButton" href="#" data-bind="click: $root.removeTask.bind($root), visible: !$root.isItemEditing($data)">
Remove</a>
</SharePoint:SPSecurityTrimmedControl>
<a class="button toolButton" href="#" data-bind="click: $root.applyTask.bind($root), visible: $root.isItemEditing($data)">
Apply</a>
<a class="button toolButton" href="#" data-bind="click: $root.cancelEdit.bind($root), visible: $root.isItemEditing($data)">
Cancel</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
对多层嵌套视图模型进行数据绑定与对单层嵌套视图模型进行数据绑定是一样的。
在下面的例子中,我将以Store -> Order -> OrderRow
为例,假设每个Store
都有一个storeName
属性,每个Order
都有一个orderNumber
属性,每个OrderRow
都有一个runningNumber
属性。我还在每个关卡上渲染了ul
中的物品。
不使用模板
要将嵌套视图模型的数据绑定到单个级别,本例中的stores
列表可以这样做:
<ul data-bind="foreach: stores">
<li>
Store Name: <span data-bind="text: storeName"></span>
</li>
</ul>
要将嵌套视图模型的数据绑定到单个级别,从Store -> Order
可以执行如下操作:
Store Name: <span data-bind="text: storeName"></span>
<ul data-bind="foreach: orders">
<li data-bind="text: orderNumber"></li>
</ul>
要将嵌套视图模型数据绑定到单个级别,从Order -> OrderRow
可以这样做:
Order number: <span data-bind="text: orderNumber"></span>
<ul data-bind="foreach: rows">
<li>
A row with running number: <span data-bind="text: runningNumber"></span>
</li>
</ul>
要在多个级别中嵌套此操作,只需将上述代码组合起来即可,移动第三个代码以替换第二个li
中的内容,然后移动第二个新代码以替换第一个li
中的内容。
<ul data-bind="foreach: stores">
<li>
Store Name: <span data-bind="text: storeName"></span>
<ul data-bind="foreach: orders">
<li>
Order number: <span data-bind="text: orderNumber"></span>
<ul data-bind="foreach: rows">
A row with running number: <span data-bind="text: runningNumber"></span>
</ul>
</li>
</ul>
</li>
</ul>
我基本上已经在http://jsfiddle.net/8yF6c/上运行了上述代码(尽管添加了用于添加新Store
, Order
和OrderRow
对象的按钮)。
为了使代码更容易维护,您可以使用模板来代替。当然,像往常一样,对于这样一个小示例,好处可能不那么明显。
在使用模板的情况下,代码基本上与上面示例中的前三种情况非常相似;在合并html之前。首先,商店的模板:<script type="text/html" id="storeTemplate">
Store Name: <span data-bind="text: storeName"></span>
<ul data-bind="foreach: orders">
<li data-bind="template: 'orderTemplate'"></li>
</ul>
</script>
然后是订单模板:
<script type="text/html" id="orderTemplate">
Order number: <span data-bind="text: orderNumber"></span>
<ul data-bind="foreach: rows">
<li data-bind="template: 'orderRowTemplate'"></li>
</ul>
</script>
最后是订单行模板。
<script type="text/html" id="orderRowTemplate">
A row with running number: <span data-bind="text: runningNumber"></span>
</script>
注意,上面三个代码部分与第一个示例的单级绑定相同,只是包装在script
元素中,类型为text/html
(以确保浏览器不会尝试将其作为脚本执行)。然后我们只需要在根级开始使用storeTemplate
。
<ul data-bind="foreach: stores">
<li data-bind="template: 'storeTemplate'"></li>
</ul>
差不多就是这样了。就像以前一样,我在http://jsfiddle.net/Ag8U3/上运行了上面的代码(尽管添加了用于添加新的Store
、Order
和OrderRow
对象的按钮)。
添加编辑和删除功能
向上述模板(或没有模板的绑定)添加编辑功能就像将span
元素更改为input
框一样简单(如果你想让其他绑定知道这个更改,你当然需要将一些属性更改为可观察的)。如果你想要不同的"模式",一个编辑模式和一个视图模式,你可以动态地选择你的模板,你可以在knockout文档中找到例子。
要添加删除功能,只需添加一个函数,当点击删除按钮时从列表中删除项目(例如在Store
对象上添加deleteOrder
函数可以是self.removeOrder = function(order){ self.orders.remove(order); };
,然后在订单中添加按钮,如<button data-bind="click: $parent.removeOrder">Remove Order</button>
)。我在http://jsfiddle.net/Ag8U3/1/的模板样例中添加了删除功能。
- 聚合Sails.JS/Waterline中的嵌套模型数据
- Sails.js - 如何更新嵌套模型
- 导轨嵌套模型形式:加载时而不是点击时
- 主干.js嵌套模型
- 在 ember 上复制嵌套模型.js(成功保存后)
- 如何在Aurelia中访问嵌套模型
- Ruby on Rails 嵌套模型细分
- 挖空嵌套模型可观察数组未定义
- 嵌套模型上的主干关系
- 如何将嵌套模型与骨干表单列表一起使用?我想用自定义模板制作一个嵌套模型
- EmberJS:使用 ajax 加载的父模型初始化嵌套模型
- AngularJS绑定到嵌套模型属性
- “嵌套模型表单”可以正确添加新字段,但 coffeescript 行为不会影响页面上现有字段等新字段
- 绑定到Ember.js中的嵌套模型
- QML:如何使用javascript创建嵌套模型
- AngularJS如何使用ng选项更新选择框中的嵌套模型
- 相同的嵌套模型'类'在Backbone.js框架中
- 主干形式的嵌套模型列表
- 如何保存嵌套模型
- Rails 3-嵌套模型的JSON没有按预期返回