Подтвердить что ты не робот

Knockout.js - привязка foreach - проверка, если последний элемент

Я использую следующий шаблон:

<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, если прошедший элемент последний в массиве?

4b9b3361

Ответ 1

Я упростил проблему, но этот jsFiddle демонстрирует возможное решение.

"если" привязка:

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

Контейнер без привязки:

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

Вы можете использовать $index в привязке foreach для получения индекса текущего связанного элемента. Используйте это для сравнения с исходной коллекцией родителя.

См. ЗДЕСЬ для получения дополнительной информации о контексте привязки.

Ответ 2

Я заметил, что существует ряд запросов на усовершенствования 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);   
    }
};

Пример использования:

<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, Two, Three and Four

Fiddle

Дальнейшее чтение

Ответ 3

Если вы НЕ, используя опцию as в привязке foreach, перейдите к наиболее ответному ответу на этот вопрос.

Если вы DO используете оператор as в привязке foreach. то этот ответ будет НЕ работать.

Вот решение в этом случае

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

ПРИМЕЧАНИЕ. Это решение работает во всех случаях, если вы используете параметр as или нет,
, но в первом случае он решает что-то, что наиболее ответили на ответ не решить

Ответ 4

Попробуйте следующее:

  • Используйте $root вместо $parent
  • Подготовьте последний элемент заранее и передайте этот элемент в свой шаблон в качестве дополнительного параметра.
  • Инкапсулировать последний элемент на наблюдаемый.