использование ng-модели во вложенных директивах ng-repeat

Я пытаюсь использовать ng-модель "внутри" директивы ng-repeat, которая сама вложена в директиву ng-repeat.

следующий jsfiddle демонстрирует мою проблему и две мои попытки ее решить.

http://jsfiddle.net/rskLy/4/

мой контроллер определяется следующим образом:

var mod = angular.module('TestApp', []);
mod.controller('TestCtrl', function ($scope) {        
var machine = {};
machine.noteMatrix = [
    [false, false, false],
    [false, true, false],
    [false, false, false]
];

$scope.machine = machine;

// ...
});

1.

<table>
    <thead>
        <tr>
            <th>--</th>
            <th ng-repeat="no in machine.noteMatrix[0]">{{$index+1}}</th>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat="track in machine.noteMatrix">
            <td>--</td>                
            <td ng-repeat="step in track">                    
                <input type="checkbox" ng-model="track[$index]"> {{step}}
            </td>
        </tr>
    </tbody>
</table>

первый пример/попытка обновляет машину.noteMatrix внутри контроллера, но каждый раз, когда флажок установлен, angularjs дважды отображает следующую ошибку в консоли javascript:

дубликаты в ретрансляторе не допускаются. Repeater: шаг в трек

и иногда он показывает эту ошибку:

дубликаты в ретрансляторе не допускаются. Репитер: нет в машине.noteMatrix[0]

2.

<table>
    <thead>
        <tr>
            <th>--</th>
            <th ng-repeat="no in machine.noteMatrix[0]">{{$index+1}}</th>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat="track in machine.noteMatrix">
            <td>--</td>                
            <td ng-repeat="step in track">                    
                <input type="checkbox" ng-model="step"> {{step}}
            </td>
        </tr>
    </tbody>
</table>

второй пример/попытка читает данные правильно из noteMatrix и никаких ошибок не отображаются в консоли javascript при установке / снятии флажков. Однако изменение их состояний не обновляет машину.noteMatrix в контроллере (нажмите кнопку" Показать матрицу", чтобы увидеть матрицу в jsfiddle).

может кто-нибудь пролить свет на это? :)

3 ответов


Это общая проблема для людей в Angular. Происходит то, что ng-repeat создает собственную область, и если вы передадите в нее массив типов значений (например, массив логических значений), обновление их не обновит родительскую область. Вам нужно передать массив ссылочных типов в ng-repeat и обновить их, чтобы он сохранялся:

вот решение, показывающее это на основе вашей скрипки

machine.noteMatrix = [
    [
        { value: false },
        { value: false }, 
        { value: false }
    ],
    [
        { value: false },
        { value: true }, 
        { value: false }
    ],
    [
        { value: false },
        { value: false }, 
        { value: false }
    ]
];

Это некрасиво, я знаю, но альтернатива уродливее. Вам нужно будет сделать что-то, чтобы управлять собственным циклом и ссылаться на значения через $parent или $parent.$родительский объект. Я не рекомендую это.


ваше первое решение кажется правильным.

Это похоже на ошибку, введенную в нестабильной ветви angularJS (вы используете 1.1.4, который нестабилен - стабильная версия 1.0.6 работает так, как ожидалось)

EDIT:

оказывается, это не ошибка, а новая функция-директива ngRepeat теперь позволяет определить функцию отслеживания (связывая идентификатор модели с элементом DOM) и больше не позволяет эти переменные отслеживания должны быть повторены. См.соответствующее совершения, the документы для 1.1.4 на ngRepeat и изменений


вам не нужно изменять свою модель или обращаться к $parent. Чего не хватает, так это "track by $index":

    <tr ng-repeat="track in machine.noteMatrix">
        <td>--</td>                
        <td ng-repeat="step in track track by $index">                    
            <input type="checkbox" ng-model="track[$index]"> {{step}}
        </td>
    </tr>

вот он в yr fiddle.

дополнительная информация: угловой ng-повторите dupes

Я не уверен, если track by существовал еще, когда был задан вопрос, поэтому другие ответы, возможно, были правильными в то время, но в current Angular это путь.