web-dev-qa-db-ja.com

ネストされたng-repeatディレクティブ内でng-modelを使用する

それ自体がng-repeatディレクティブにネストされているng-repeatディレクティブの「内部」でng-modelを使用しようとしています。

次のjsfiddleは、私の問題とそれを解決するための2つの試みを示しています。

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はjavascriptコンソールに次のエラーを2回表示します。

リピーターでの複製は許可されていません。リピーター:ステップイントラック

また、次のエラーが表示されることもあります。

リピーターでの複製は許可されていません。リピーター: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>

2番目の例/試行はnoteMatrixからデータを正しく読み取り、チェックボックスをオン/オフしてもjavascriptコンソールにエラーは表示されません。ただし、状態を変更しても、コントローラーのmachine.noteMatrixは更新されません(「マトリックスの表示」ボタンを押して、jsfiddleのマトリックスを表示します)。

誰かがこれに光を当てることができますか? :)

17
Óli Fly

これは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。$ parentオブジェクトを介して値を参照するために何かを行う必要があります。これはお勧めしません。

15
Ben Lesh

モデルを変更したり、$ parentにアクセスしたりする必要はありません。不足しているのは「$ 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>

ここでは年のフィドルです。

詳細: Angular ng-repeat dupes

質問されたときにtrack byがまだ存在していたかどうかはわかりません。そのため、他の回答はその時点で正しかった可能性がありますが、現在はAngularこれが方法です。

3
Semicolon

あなたの最初の解決策は正しいようです。

これはバグのようで、angularJSの不安定なブランチで導入されました(不安定な1.1.4を使用しています-安定バージョンの1.0.6は期待どおりに機能します)

編集:

これはバグではないことが判明しましたが、新機能-ngRepeatディレクティブで追跡関数を定義できるようになり(モデルのIDをDOM要素に関連付ける)、これらの追跡変数を繰り返すことができなくなりました。 対応するコミットngRepeatの1.1.4のドキュメント および 変更ログ を参照してください。

3
Tiago Roldão