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

发布于 2025-01-03 15:08:43 字数 1862 浏览 0 评论 0原文

我正在使用以下模板:

<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());}

如果传递的元素位于数组中的最后一个,则将函数添加到我的视图模型中,该函数返回 true/false 是我唯一的选择吗?

I am using the following template:

<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>

I get this error in the console:

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());}

Is my only option to add a function to my viewmodel that returns true/false if the passed element is last in the array?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

猫瑾少女 2025-01-10 15:08:43

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

“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 来获取当前绑定项的索引。用它来与父级的原始集合进行比较。

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

I've simplified the problem, but this jsFiddle demonstrates a possible solution.

"if" binding:

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

Containerless "if" binding:

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

You can use $index within a foreach binding to get the index of the currently bound item. Use that to compare against the original collection of the parent.

See HERE for more information regarding binding contexts.

昨迟人 2025-01-10 15:08:43

我注意到有许多请求增强 KO 以支持 $length$last$array 中的保留属性code>foreach 绑定,尽管由于各种原因(通常是性能),它们还没有进入代码库。

如果有人有兴趣使用自定义绑定针对特定情况公开这些元素,这里有一个公开 $length 变量以打印“漂亮”列表的简单示例。
您只需在通常使用 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>

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

输出: One,二、三、四

小提琴

进一步阅读

I noticed there are a number of requests for enhancements to KO to support the $length, $last, or $array reserved properties in the foreach binding although, for a variety of reasons (often performance), they have not made it into the codebase.

If anyone is interested in exposing these elements for a specific case using a custom binding, here is a simple example of exposing the $length variable in order to print a "pretty" list.
You simply use forEachWithLength anywhere you would normally use 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);   
    }
};

Example usage:

<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"]

Output : One, Two, Three and Four

Fiddle

Further reading

明月松间行 2025-01-10 15:08:43

如果您foreach绑定中使用as选项,那么请转到此问题得票最多的答案

如果您在 foreach 绑定中DO使用 as 运算符。那么这个答案将不起作用

这是这种情况下的解决方案

<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()
在我的例子中,它被命名为 Items,因此我将 $parent.data() 替换为 $parent.Items ()

注意此解决方案在所有情况下都有效(无论您是否在 foreach 中使用 as 选项

If you are NOT using as option in the foreach binding, then go to the most-upvoted answer to this question.

If you are DO using as operator in the foreach binding. then that answer will NOT work.

Here is the solution in that case

<div data-bind="foreach:{data: Items, as :'item'}">
    <div data-bind="if: ($index() === ($parent.Items().length - 1))">I'm the last element</div>
</div>

The secret with replacing the $parent.data() with the name of the observable array you are using.
In my case it was named Items, so I replaced the $parent.data() with $parent.Items()

Note this solution is working in all cases, (in case you are using as option in foreach or not)

甜尕妞 2025-01-10 15:08:43

请尝试以下操作:

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

Try the following:

  1. Use $root instead of $parent
  2. Prepare the last item in advance and pass this item to your template as additional parameter.
  3. Encapsulate the last element to observable.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文