我相信这对某些人来说是一个简单的答案。我有以下ViewModel:
@{
var initialData = new JavaScriptSerializer().Serialize(Model);
}
var data = @Html.Raw(initialData);
function ViewModel(data) {
var self = this;
self.Name = ko.observable(data.Name);
self.Items = ko.observableArray(data.Items);
self.addItem = function() { self.Items.push(""); };
self.removeItem = function(data) { self.Items.remove(data); }
}
$(document).ready(function() {ko.applyBindings(new ViewModel(data)); });
以下视图:
<div>
Name: <span data-bind="text: Name"></span>
</div>
<div>
Items: <button data-bind="click: addItem">Add Item</button>
</div>
<div>
<table>
<tbody data-bind="template: { name: 'itemTemplate', foreach: Items }"></tbody>
</table>
</div>
<script type="text/html" id="itemTemplate">
<tr>
<td>
<input data-bind="value: $data" />
<a href="#" data-bind="click: function() {$parent.removeItem($data)}">Remove Item</a>
</td>
</tr>
</script>
除了removeItem
之外,一切似乎都能正常工作。添加新行并在空的新行上单击“删除项”时,将删除所有新行。我看了很多淘汰教程试图让这个工作,我的方法似乎是一个有效的尝试,但显然......我必须遗漏一些东西。有什么建议吗?
答案 0 :(得分:14)
observableArray的remove
函数循环遍历数组,并删除与传递给它的值匹配的所有项。在你的情况下,你只是处理字符串,它将看到所有新的(没有值)将匹配“”。
有几种方法可以处理它:
您可以处理对象而不仅仅是{ value: ko.observable("") }
之类的字符串。然后,当您传递$data
时,它将仅删除与该对象引用匹配的实际项目。如果您的值不可观察且是数据本身(不是属性),那么您的写入实际上不会使其返回到您的视图模型。
如果这对您的方案不起作用,那么您可以使用splice删除基于索引($index
)的项目。
我可能会这样做:http://jsfiddle.net/rniemeyer/N3JaW/
另请注意,event
(click
是event
)包装器的绑定将当前数据作为处理程序的第一个参数传递,因此您可以简化绑定到{ {1}}。
更新:您可以使用以下几种方法控制对象转换为JSON的方式:
click: $parent.removeItem
将其第二和第三个参数传递给ko.toJSON
。第二个arg让你运行一个函数来替换here所描述的值。下面是一个示例,它检查密钥是否为数字(数组项)并且具有JSON.stringify
属性。如果是这样,它只返回字符串而不是对象。 http://jsfiddle.net/rniemeyer/N3JaW/1/
如果对对象使用构造函数,则可以按照here所述覆盖value
函数。以下是具有此功能的示例:http://jsfiddle.net/rniemeyer/N3JaW/2/
可以使用的另一种技术是维护具有“良好”值的计算可观察量。以下是示例:http://jsfiddle.net/rniemeyer/N3JaW/3/。在这一个toJSON
中是一个计算的observable,它返回clean值。 Items
包含值的对象版本。转换为JSON时,Items.asObjects
部分在asObjects
转换为JSON时自然会被删除。如果您在转换为JSON时只需要这个“好”数组,那么其他选项对于性能更好(它们只在您想要发送时计算)。