我有这个HTML,并尝试使用它来生成一个表,其中包含添加更多行的选项:
<thead>
<tr>
<th>Item</th>
<th>Cost</th>
<th>Amount</th>
<th>
<button class="btn btn-default" data-bind="click: addItem">Add Item</button>
</th>
</tr>
</thead>
<tbody data-bind="foreach: items">
<tr>
<td data-bind="template: {name: $parent.dynTemplate, data: item }">
<td data-bind="template: {name: $parent.dynTemplate, data: cost() }"></td>
<td data-bind="template: {name: $parent.dynTemplate, data: amount() }">
<td></td>
</tr>
</tbody>
我正在使用两种不同的模板:
<script id="inpTmp" type="text/html">
<input data-bind="value: $data" />
</script>
<script id="dispTmp" type="text/html">
<p data-bind="text: $data"></p>
</script>
我正在根据dynTemplate
函数的结果选择调用哪一个。我为此提供动力的淘汰赛非常简单:
function ItemAdd(name, icost, iamount) {
var self = this;
self.item = name;
self.cost = ko.observable(icost);
self.amount = ko.observable(iamount);
}
function TestModel() {
var self= this;
self.items= ko.observableArray([
new ItemAdd("a", 5, 10),
new ItemAdd("b", 6, 4)
]);
self.addItem= function() {
self.items.push(new ItemAdd("", 0, 0));
};
self.dynTemplate= function(init, s) {
if(init=== 0 || init=== '') {
return 'inpTmp';
}
return 'dispTmp';
};
}
ko.applyBindings(new TestModel());
我遇到的问题是,当我在新创建的行中输入值时,items
中的值不会改变。它们正确初始化,但是当我运行一个函数来记录items
中的值时,它们仍然是默认值。如果我使用knockout if
语句,那么一切都会正确更新。但是,使用6组if
语句似乎不是很有效,所以我想看看是否可以将其拉出一个函数,然后发回适当的模板。当值为""
或0时,我正在尝试输入,然后在输入内容时将其更改为<p>
。
我已尝试更改数据传递到模板的方式,我尝试使用with
分配上下文,但无济于事。除非dynTemplate
或$root
作为前缀,否则调用$parent
无效。如果这正在改变上下文,有没有办法重置它?
这是上下文的问题,如果是,有没有办法用dynTemplate
函数分配上下文?或者模板中新创建的元素是否未正确绑定?我搜索了很多,并在foreach循环中找到了模板,但没有看到用于应用它们的函数。如果有更好的方法,请告诉我。
感谢您的帮助
答案 0 :(得分:2)
您当前的示例无法正常工作,因为ko依赖性攻击者未发现您的模型字段已更改。这是因为&#39; init&#39;是展开的值(不是可观察的)。 这个小提琴展示了如何使它与单个项目一起使用。领域。 http://jsfiddle.net/tabalinas/VXXqr/
在这个更改版本的dynTemplate中,我们得到了observable的值,因此依赖关系跟踪器可以看到该值已更改。当然,我们需要更改模板。
self.dynTemplate= function(item, s) {
var val = item.item();
if(val=== 0 || val=== '') {
return 'inpTmp';
}
return 'dispTmp';
};
<script id="inpTmp" type="text/html">
<input data-bind="value: $data.item" />
</script>
<script id="dispTmp" type="text/html">
<p data-bind="text: $data.item"></p>
</script>
对于您的情况,您需要所有字段的通用模板,您可以执行以下操作:将字段名称作为数据传递。该模板将从$ parent中获取数据。 dynTemplate func也相应更改。
<tbody data-bind="foreach: items">
<tr>
<td data-bind="template: {name: $parent.dynTemplate, data: 'item' }">
</td>
<td data-bind="template: {name: $parent.dynTemplate, data: 'cost' }">
</td>
<td data-bind="template: {name: $parent.dynTemplate, data: 'amount' }">
</td>
</tr>
</tbody>
<script id="inpTmp" type="text/html">
<input data-bind="value: $parent[$data]" />
</script>
<script id="dispTmp" type="text/html">
<p data-bind="text: $parent[$data]"></p>
</script>
self.dynTemplate= function(field, context) {
var value = context.$parent[field]();
if(value=== 0 || value=== '') {
return 'inpTmp';
}
return 'dispTmp';
};