Knockout.js - foreach绑定 - 测试最后一个元素

Jon*_*han 41 javascript knockout.js

我使用以下模板:

<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>
Run Code Online (Sandbox Code Playgroud)

我在控制台中收到此错误:

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());}
Run Code Online (Sandbox Code Playgroud)

我唯一的选择是向我的viewmodel添加一个函数,如果传递的元素在数组中的最后一个,则返回true/false?

Bre*_*tin 79

我已经简化了问题,但是这个jsFiddle演示了一个可能的解决方案.

"if"绑定:

<div data-bind="if: ($index() === ($parent.data().length - 1))">I'm the last element</div>
Run Code Online (Sandbox Code Playgroud)

无容器"if"绑定:

<!-- ko if: ($index() === ($parent.data().length - 1)) -->
<div>I'm the last element again</div>
<!-- /ko -->
Run Code Online (Sandbox Code Playgroud)

您可以$indexforeach绑定中使用以获取当前绑定项的索引.用它来比较父母的原始集合.

有关绑定上下文的更多信息,请参阅此处.


mwi*_*but 10

我注意到有用于增强KO支持多个请求$length,$last$array在保留性能foreach的结合,虽然,对各种原因(往往表现),他们没有把它做成的代码库.

如果有人有兴趣使用自定义绑定为特定情况公开这些元素,这里是一个公开$length变量以打印"漂亮"列表的简单示例.
您只需使用forEachWithLength通常使用的任何地方foreach.

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);   
    }
};
Run Code Online (Sandbox Code Playgroud)

用法示例:

<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>
Run Code Online (Sandbox Code Playgroud)

输入: ["One", "Two", "Three", "Four"]

输出: One, Two, Three and Four

小提琴

进一步阅读


Mad*_*man 0

请尝试以下操作:

  1. 使用$root而不是$parent
  2. 提前准备最后一项,并将此项作为附加参数传递到您的模板。
  3. 将最后一个元素封装为可观察的。