Knockout.js – foreach绑定 – testing是否最后一个元素
我正在使用以下模板:
<div class="datatypeOptions" data-bind="if: $data.datatypeTemplate().allowOptions"> <h3>Allowed responses</h3> <p data-bind="if: $data.datatypeTemplate().datatypeOptions().length == 0">There are no responses for this question, yet. <a href="#" data-bind="click: function(d, e){$root.addDatatypeOption($data.datatypeTemplate());}">Add one</a> <ul data-bind="foreach: $data.datatypeTemplate().datatypeOptions()"> <li> <a href="#" data-bind="text: name, click: $root.selectedDatatypeOption, visible: $data !== $root.selectedDatatypeOption()"></a> <input data-bind="value: name, visibleAndSelect: $data === $root.selectedDatatypeOption(), event: { blur: $root.clearDatatypeOption }, executeOnEnter: { callback: function(){ $root.addDatatypeOption($parent.datatypeTemplate()); } }" /> //I want to show this a tag only if $data is the last element in the array. Problem here ===> <a href="#" data-bind="if: $data == $parent.datatypeTemplate().datatypeOptions()[ $parent.datatypeTemplate().datatypeOptions().length - 1 ], click: function(d, e){$root.addDatatypeOption($data.datatypeTemplate());}"><img src='/static/img/icons/custom-task-wizard/black/plus_12x12.png' title='Add option'></a> </li> </ul> </div>
我在控制台中得到这个错误:
Uncaught Error: Unable to parse bindings. Message: TypeError: Object [object Object] has no method 'datatypeTemplate'; Bindings value: if: $data == $parent.datatypeTemplate().datatypeOptions()[ $parent.datatypeTemplate().datatypeOptions().length - 1 ], click: function(d, e){$root.addDatatypeOption($data.datatypeTemplate());}
是我唯一的select添加一个函数到我的viewmodel返回true / false如果传入的元素是在数组中的最后一个?
我简化了这个问题,但是这个jsFiddle演示了一个可能的解决scheme。
“if”绑定:
<div data-bind="if: ($index() === ($parent.data().length - 1))">I'm the last element</div>
无容器“if”绑定:
<!-- ko if: ($index() === ($parent.data().length - 1)) --> <div>I'm the last element again</div> <!-- /ko -->
您可以在foreach
绑定中使用$index
来获取当前绑定项目的索引。 使用它来比较父级的原始集合。
有关绑定上下文的更多信息,请参阅这里 。
我注意到有很多对KO进行增强的请求,以支持foreach
绑定中的$length
, $last
或$array
保留属性,但由于各种原因(通常是性能),它们并没有将其放入代码库。
如果任何人有兴趣使用自定义绑定来暴露这些元素的特定情况下,这是一个简单的例子暴露$length
variables,以便打印一个“漂亮”的列表。
你只要在任何你通常使用foreach
地方使用forEachWithLength
。
ko.bindingHandlers.forEachWithLength = { init: function (element, valueAccessor, allBindingsAccessor, viewModel, context) { return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, context); }, update: function (element, valueAccessor, allBindingsAccessor, viewModel, context) { var array = ko.utils.unwrapObservable(valueAccessor()); var extendedContext = context.extend({"$length" : array.length }); ko.bindingHandlers.foreach.update(element, valueAccessor, allBindingsAccessor, viewModel, extendedContext); } };
用法示例:
<div data-bind="forEachWithLength: myArray"> <span data-bind="text: $data"></span> <!-- ko if: ($index() < $length-2) -->, <!-- /ko --> <!-- ko if: ($index() === $length-2) --> and <!-- /ko --> </div>
input: ["One", "Two", "Three", "Four"]
输出: One, Two, Three and Four
小提琴
进一步阅读
如果你没有在foreach
绑定中使用这个选项,那么请回到这个问题的最上面的答案 。
如果你在使用foreach
绑定中的操作符。 那么这个答案将无法正常工作。
这是在这种情况下的解决scheme
<div data-bind="foreach:{data: Items, as :'item'}"> <div data-bind="if: ($index() === ($parent.Items().length - 1))">I'm the last element</div> </div>
将$parent.data()
replace为你正在使用的observable数组的名字的秘诀在我的例子中,它被命名为Items
,所以我用$parent.data()
replace了$parent.Items()
注意, 这个解决scheme在所有情况下都可以工作,如果你使用的as
选项,
但是在第一种情况下,它解决了最有争议的答案没有解决的问题
尝试以下操作:
- 使用
$root
而不是$parent
- 提前准备最后一个项目,并将此项目作为附加parameter passing给您的模板。
- 将最后一个元素封装为可观察的。