Добавить полосатый стиль в список предметов

Как лучше всего составить список с помощью KnockoutJS? Класс в div ниже должен быть четным или нечетным в зависимости от того, где он находится в списке, и обновляться при добавлении или удалении элементов.

<div class="Headlines loader" 
     data-bind="css: { loader: headlines().length == 0 }, 
                       template: { name: 'recentHeadlinesTemplate',
                                   foreach: beforeHeadlineAddition, 
                                   beforeRemove: function(elem) { $(elem).slideUp() },
                                   afterAdd: slideDown }">
</div>

<script type="text/html" id="recentHeadlinesTemplate">
    <div class="even">
        ${Title}
    </div>  
</script>

6 ответов

Решение

Некоторое время назад на форумах KO была тема для этого: https://groups.google.com/d/topic/knockoutjs/cJ2_2QaIJdA/discussion

Решение, которое у меня было, было пользовательской привязкой. Было несколько вариантов, но в основном это будет выглядеть так:

ko.bindingHandlers.stripe = {
    update: function(element, valueAccessor, allBindingsAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor()); //creates the dependency
        var allBindings = allBindingsAccessor();
        var even = allBindings.evenClass;
        var odd = allBindings.oddClass;

        //update odd rows
        $(element).children(":nth-child(odd)").addClass(odd).removeClass(even);
        //update even rows
        $(element).children(":nth-child(even)").addClass(even).removeClass(odd);;
    }
}

и использоваться как:

<ul data-bind="template: { name: 'itemsTmpl', foreach: items }, stripe: items, evenClass: 'light', oddClass: 'dark'"></ul>

Пример здесь с 3 вариантами этой привязки:

http://jsfiddle.net/rniemeyer/HJ8zJ/

Я нашел функцию, которая возвращает индекс при итерации с foreach, поэтому вы можете применять четные и нечетные классы достаточно компактным способом, например:

<tr data-bind="css: { 'even': ($index() % 2 == 0) }">

Одним из простых способов сделать это является добавление вычисляемой наблюдаемой, которая добавляет индекс к каждому элементу, например

    self.logLines = ko.observable(logLinesInput);

    self.enhancedLogLines = ko.computed(function() {
        var res = [];
        $.each(self.logLines(), function(index, ll) { 
             res.push(new LogLine(index, ll)); 
        });
        return res;
    }, self);

В моем случае LogLine() создает объект с индексным полем и другими полями, которые были в исходном объекте.

Теперь вы можете легко добавить зебры в ваш вывод:

            <tr data-bind="css: { odd: (index % 2 == 1), even: (index % 2 == 0) }">

Спасибо за полезные посты. Я хотел бы упомянуть, что css может хорошо справиться с чередованием, но встроенное "если", кажется, функционирует только после того, как строка была отрисована. Поэтому использование $ index или возможности css odd / even не дают желаемых результатов. Не используя шаблон, я обнаружил, что вы можете обернуть логику KO вокруг строки, чтобы логика возникала до того, как строка будет подсчитана.

<tbody data-bind="foreach: viewModel.configuration().items()"">
    <!-- ko if: $data.part() != '' -->
    <tr>
            <td data-bind="text: $index"></td><td  data-bind="text: $data.part()"></td>
    </tr>
    <!-- /ko -->
</tbody>

Вот полный пример:

<ul class="pickupPointHours" data-bind="foreach: Items">
 <li data-bind="css: { lineEven: ($index()%2 === 0), lineOdd: ($index()%2 === 1)}">
  <span class="pickupPointDay" data-bind="text: TextProperty"></span>
 </li>
</ul>

Вы можете использовать условные операторы {{if}} и {{else}} внутри шаблона, чтобы установить класс div.

Также вам нужно будет расширить вашу модель представления, чтобы она включала функцию, которая возвращает индекс вашего текущего элемента, который сообщает вам, является ли он нечетным или четным. (Как то так)

Другие вопросы по тегам