web-dev-qa-db-ja.com

ng-model、ng-repeat、および入力の難しさ

ngRepeatngModelを使用して、ユーザーがアイテムのリストを編集できるようにしようとしています。 ( このフィドルを参照 。)しかし、私が試みた両方のアプローチは奇妙な振る舞いにつながりました:1つはモデルを更新せず、もう1つは各キーダウンでフォームをぼかします。

ここで何か間違ったことをしていますか?これはサポートされているユースケースではありませんか?

便宜上、コピーされたフィドルのコードを次に示します。

<html ng-app>
    <head>
        <link href="//netdna.bootstrapcdn.com/Twitter-bootstrap/2.2.1/css/bootstrap-combined.min.css" rel="stylesheet">
    </head>
    <body ng-init="names = ['Sam', 'Harry', 'Sally']">
        <h1>Fun with Fields and ngModel</h1>
        <p>names: {{names}}</p>
        <h3>Binding to each element directly:</h3>
        <div ng-repeat="name in names">
            Value: {{name}}
            <input ng-model="name">                         
        </div>
        <p class="muted">The binding does not appear to be working: the value in the model is not changed.</p>
        <h3>Indexing into the array:</h3>
        <div ng-repeat="name in names">
            Value: {{names[$index]}}
            <input ng-model="names[$index]">                         
        </div>
        <p class="muted">Type one character, and the input field loses focus. However, the binding appears to be working correctly.</p>
    </body>
</html>

115
Nick Heiner

これは拘束力のある問題のようです。

アドバイスは プリミティブにバインドしない です。

ngRepeatは、コレクション内の文字列を繰り返し処理しています(オブジェクトを繰り返し処理する必要がある場合)。問題を解決するには

<body ng-init="models = [{name:'Sam'},{name:'Harry'},{name:'Sally'}]">
    <h1>Fun with Fields and ngModel</h1>
    <p>names: {{models}}</p>
    <h3>Binding to each element directly:</h3>
    <div ng-repeat="model in models">
        Value: {{model.name}}
        <input ng-model="model.name">                         
    </div>

jsfiddle: http://jsfiddle.net/jaimem/rnw3u/5/

120
jaime

Angular最新バージョン(1.2.1)を使用し、$indexで追跡します。この問題は修正されました

http://jsfiddle.net/rnw3u/53/

<div ng-repeat="(i, name) in names track by $index">
    Value: {{name}}
    <input ng-model="names[i]">                         
</div>
70
Thilaga

scopesngRepeat および ngModel with NgModelController の仕組みを理解する必要がある場合、困難な状況に陥ります。また、1.0.3バージョンを使用してみてください。あなたの例は少し異なる動作をします。

Jm-が提供するソリューションを簡単に使用できます。

しかし、状況をより深く処理したい場合は、理解する必要があります。

  • AngularJSの仕組み ;
  • スコープには階層構造があります。
  • ngRepeatは、すべての要素に対して新しいスコープを作成します。
  • ngRepeatは追加情報(hashKey)を持つアイテムのキャッシュを構築します。 (キャッシュにない)すべての新しいアイテムの各watch呼び出しで、ngRepeatは新しいスコープ、DOM要素などを構築します。 詳細な説明
  • 1.0.3からngModelControllerは、実際のモデル値で入力を再レンダリングします。

AngularJS 1.0.3の例「各要素への直接バインド」の仕組み:

  • 入力に文字'f'を入力します。
  • ngModelControllerは項目スコープのモデルを変更します(names配列は変更されません)=> name == 'Samf'names == ['Sam', 'Harry', 'Sally'];
  • $digestループが開始されます。
  • ngRepeatは、項目スコープ('Samf')からのモデル値を、変更されていない名前配列('Sam')からの値で置き換えます。
  • ngModelControllerは、実際のモデル値('Sam')で入力を再レンダリングします。

「配列へのインデックス付け」の例の仕組み:

  • 入力に文字'f'を入力します。
  • ngModelControllerは名前の項目を変更しますarray => `names == ['Samf'、 'Harry'、 'Sally'];
  • $ digestループが開始されます。
  • ngRepeatはキャッシュで'Samf'を見つけることができません。
  • ngRepeatは新しいスコープを作成し、新しい入力を持つ新しいdiv要素を追加します(そのため入力フィールドがフォーカスを失います-古い入力を持つ古いdivは新しい入力を持つ新しいdivに置き換えられます)。
  • 新しいDOM要素の新しい値がレンダリングされます。

また、 AngularJS Batarang を使用して、入力した入力でdivのスコープの$ idがどのように変化するかを確認することもできます。

43
Artem Andreev

キーストロークごとにモデルを更新する必要がない場合は、nameにバインドしてからblurイベントで配列項目を更新するだけです:

<div ng-repeat="name in names">
    Value: {{name}}
    <input ng-model="name" ng-blur="names[$index] = name" />
</div>
6
Bill Heitstuman

AngularJsを1.1.2に更新したところ、問題ありません。このバグは修正されたと思います。

http://ci.angularjs.org/job/angular.js-pete/57/artifact/build/angular.js

4
Anton Rodin

問題は、ng-modelinputでどのように動作し、nameオブジェクトを上書きするかによって、ng-repeatが失われることにあるようです。

回避策として、次のコードを使用できます。

<div ng-repeat="name in names">
    Value: {{name}}
    <input ng-model="names[$index]">                         
</div>

それが役に立てば幸い

2
Draško Kokić

私はそれが魅力のように働いた私の問題のために上記の解決策を試しました。ありがとう!

http://jsfiddle.net/leighboone/wn9Ym/7/

これが私のバージョンです:

var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
    $scope.models = [{
        name: 'Device1',
        checked: true
    }, {
        name: 'Device1',
        checked: true
    }, {
        name: 'Device1',
        checked: true
    }];

}

そして私のHTML

<div ng-app="myApp">
    <div ng-controller="MyCtrl">
         <h1>Fun with Fields and ngModel</h1>
        <p>names: {{models}}</p>
        <table class="table table-striped">
            <thead>
                <tr>
                    <th></th>
                    <th>Feature 1</td>
                    <th>Feature 2</th>
                    <th>Feature 3</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Device</td>
                   <td ng-repeat="modelCheck in models" class=""> <span>
                                    {{modelCheck.checked}}
                                </span>

                    </td>
                </tr>
                <tr>
                    <td>
                        <label class="control-label">Which devices?</label>
                    </td>
                    <td ng-repeat="model in models">{{model.name}}
                        <input type="checkbox" class="checkbox inline" ng-model="model.checked" />
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</div>
1
Leigh Lawhon