Каков наилучший способ обработки многомерных массивов в Knockout JS?

Каков стандартный способ работы с многомерными массивами с помощью Knockout?

Допустим, вы хотите сгенерировать динамическую таблицу с помощью KnockoutJS. Строки и столбцы таблицы генерируются из observableArrays. Данные внутри каждой ячейки также являются наблюдаемыми (данные привязаны к текстовым полям). Данные внутри каждой ячейки также должны быть проверены методом нокаута.

Я использую что-то подобное для генерации значения моих текстовых полей:

data-bind="value: $root.qty[$index()][$parentContext.$index()]"

Это внутри двух foreach для tbody:

<tbody data-bind="foreach: $root.styleColors">
    <tr>
        <td data-bind="text: StyleColorName, visible: $root.showFirstColumn"></td>
        <!-- ko foreach: $root.sizes -->
            <td>
                <input type="text" class="qty" data-bind="value: $root.qty[$index()][$parentContext.$index()]"/>
            </td>
        <!-- /ko -->
    </tr>
</tbody>

Это работает хорошо, но мне нужно иметь возможность динамически изменять данные в зависимости от того, какой элемент я редактирую. Как только я изменяю количество столбцов или строк, это вызывает всевозможные проблемы. Я уменьшил многие из этих проблем, используя расширитель throttle, заставив рендеринг ждать обеих строк. и столбцы, наблюдаемые перед рендерингом.

Каждый раз, когда я меняю текущий редактируемый элемент, я регенерирую многомерный массив qty[][] с использованием простых массивов javascript, и каждое фактическое значение является наблюдаемым.

Вот пример типичной проблемы, которая у меня есть. Для этого конкретного примера я проверяю минимальное и максимальное значение для моих количественных значений (ячеек). Но я получаю следующее исключение (Uncaught TypeError: не удается прочитать «правила» свойств неопределенного значения), когда я перепривязываю таблицу, содержащую меньше строк или меньше столбцов. Я меняю observableArrays для строк и столбцов, привязка data-bind="$root.qty[$index()][$parentContext.$index()]" больше недействительна, потому что один из индексов выходит за пределы граница.

Что мне не хватает?

Спасибо!


person EtienneT    schedule 14.03.2013    source источник


Ответы (1)


Я не могу ответить на ваш вопрос, не видя больше кода модели представления, но ваш путь звучит сложно. - если вы не можете понять, как контролировать, в каком порядке нокаут оценивает добавление/удаление, вы столкнетесь с проблемами индексации. Я расскажу вам, как я решил проблему с таблицей.

Кроме того, т.е., особенно 8 вниз, очень привередлив к таблицам изменения кода javascript. тест тест тест!

Я в основном изменил простую сетку Сандерсона - я бы проверил это и посмотрел, работает ли это для вас вообще.

https://github.com/SteveSanderson/knockout/tree/gh-pages/examples/resources

Вместо создания многомерного массива используйте один массив для ваших столбцов, а затем другой массив для ваших строк. Каждый элемент в массиве строк на самом деле является объектом с разными именами столбцов в качестве ключей и объектов в качестве значения.

So....

//two columns
this.columns = ko.observableArray(["Column1","Column2"]);

//two Rows
this.rowData = ko.observableArray([
{Column1:{StyleColorName:"Top Left"},Column2:{StyleColorName:"Top Right"}},
{Column1:{StyleColorName:"Bottom Left"},Column2:{StyleColorName:"Bottom Right"}}
]);

А и разметка

<thead>
    <tr>
        <th data-bind="visible:showFirstColumn">First Column</th>
        <!-- ko foreach: $root.sizes -->
        <th data-bind="text:$data" ></th>
        <!-- /ko -->
    </tr>
</thead>
<tbody data-bind="foreach: rowData">
    <tr>
        <td data-bind="text: StyleColorName, visible: $root.showFirstColumn"></td>
        <!-- ko foreach: columns -->
            <td>
                <input type="text" class="qty" data-bind="value:$parent[$data].StyleColorName()"/>
            </td>
        <!-- /ko -->
    </tr>
</tbody>
person scaryman    schedule 14.03.2013