2013-04-12 5 views
17

Я пытаюсь использовать ng-модель «внутри» директивы ng-repeat, которая сама вложена в директиву ng-repeat.с использованием ng-модели в вложенных директивах 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> 

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

Duplicates in a repeater are not allowed. Repeater: step in track

, а иногда он также будет отображать сообщение об ошибке:

Duplicates in a repeater are not allowed. Repeater: no in machine.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 при проверке/снятии флажков. Однако изменение их состояний не обновляет machine.noteMatrix в контроллере (нажмите кнопку «Показать матрицу», чтобы увидеть матрицу в jsfiddle).

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

+0

Свойство $ scope изменяется при использовании ng-repeat, поэтому попробуйте использовать $ parent.track [$ index] вместо этого, чтобы получить доступ к внешней области. –

+0

с использованием $ parent.track [$ index] вместо отслеживания [$ index] приводит к тому, что те же 'Duplicates в повторителе не разрешены. Повторитель: шаг в ошибке трека –

+0

в новой угловой ошибке есть два указательных пункта https://github.com/angular/angular.js/blob/master/CHANGELOG.md –

ответ

14

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

Here is a solution showing this based off of your fiddle

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

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

+1

А я думаю, что это потому, что javascript «проходит по значению», поэтому примитивные типы «копируются», а значение объектной переменной является ссылкой на объект. Это вычисляет? –

+1

Это правильно. Это связано с тем, как области прототипов наследуют родительскую область. –

+0

Sweet. Отметьте это как правильный ответ. Мой пользовательский интерфейс Drum Machine работает так, как планировалось. –

3

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

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

EDIT:

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

+0

Спасибо! Возвращаясь к 1.0.6, вы избавитесь от ошибок JavaScript. Я перешел от 1.0.6 до 1.1.4, потому что использование вторых решений с 1.0.6 привело к тому, что флажки не меняли состояния. Перемещение до неустойчивого 1.1.4 исправлено, но привело к тому, что noteMatrix в контроллере не обновляется. :( –

3

Вам не нужно изменять вашу модель или обращаться к $ parent. Что хватает «трэк $ индекса»:

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

Here it is in yr fiddle.

Дополнительной информации: Angular ng-repeat dupes

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

+0

Спасибо, недостающей частью для меня было использование трека 'ng-model =" [$ index] "' вместо 'ng-model =" step "' – Blowsie