Трудности с НГ-модель, НГ-повторите, а входы


Я пытаюсь разрешить пользователю редактировать список элементов с помощью ngRepeat и ngModel. (видите эту скрипку.) Однако оба подхода, которые я пробовал, приводят к странному поведению: один не обновляет модель, а другой размывает форму на каждом keydown.

Я делаю что-то неправильно здесь? Это не поддерживаемый вариант использования?

вот код из скрипки, скопированный для удобства:

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

8 112

8 ответов:

это, кажется, является обязательным вопросом.

советы не привязывайтесь к примитивам.

код 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/

использование угловой последней версии (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>

вы попадаете в сложную ситуацию, когда нужно понять, как области,ngRepeat и ngModel С NgModelController работа. Также попробуйте использовать версию 1.0.3. Ваш пример будет работать немного по-другому.

вы можете просто использовать решение, предоставленное jm -

но если вы хотите справиться с ситуацией более глубоко, вы должны понять:

  • как AngularJS не работает;
  • области имеют иерархическую структуру;
  • ngRepeat создает новую область для каждого элемента;
  • ngRepeat построить кэш элементов с дополнительной информацией (hashKey); на каждой прямой вызов для каждого нового элемента (то есть не в кэше) ngRepeat создает новый контекст, DOM-элемент, и т. д. более подробное описание.
  • от 1.0.3 ngmodelcontroller rerenders входы с фактической моделью ценности.

как ваш пример "привязка к каждому элементу напрямую" работает для AngularJS 1.0.3:

  • введите букву 'f' на входе;
  • ngModelController изменяет модель для области элемента (массив имен не изменяется) =>name == 'Samf',names == ['Sam', 'Harry', 'Sally'];
  • $digest цикл запускается;
  • ngRepeat заменяет значение Модели из области элемента ('Samf') по значению из массива неизмененных имен ('Sam');
  • ngModelController rerenders ввод с фактическим значением модели ('Sam').

как работает ваш пример "индексирование в массив":

  • введите букву 'f' на входе;
  • ngModelController изменяет элемент в именах array = > ' names = = ['Samf', 'Harry','Sally'];
  • $digest цикл запущен;
  • ngRepeat не могу найти 'Samf' в кэш;
  • ngRepeat создает новую область, добавляет новый элемент div с новым входом (именно поэтому вход поле теряет фокус-старый div со старым входом заменяется новым div с новым входом);
  • отображаются новые значения для новых элементов DOM.

также вы можете попробовать использовать AngularJS Batarang и посмотрите, как изменяется $id области div с вводом, в который вы вводите.

Если вам не нужна модель для обновления с каждым нажатием клавиши, просто привязать к name а затем обновить элемент массива на событие размытия:

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

Я только что обновил AngularJs до 1.1.2 и не имею никаких проблем с ним. Я думаю эта ошибка была исправлена.

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

проблема, кажется, в том, как ng-model работает с input и перезаписывает name объект, что делает его потерянным для ng-repeat.

в качестве обходного пути можно использовать следующий код:

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

надеюсь, что это помогает

я попробовал решение выше для моей проблемы в нем работал как шарм. Спасибо!

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>

Как сделать что-то вроде:

<select ng-model="myModel($index+1)">

и в моем элементе инспектора быть:

<select ng-model="myModel1">
...
<select ng-model="myModel2">