Подтвердить что ты не робот

Связывание входных данных с массивом примитивов с использованием ngRepeat => неизменяемых входов

Ниже приведена демонстрация моей проблемы.

$scope.myNumbers = [10, 20, 30];

<div ng-repeat="num in myNumbers">
    <input type="text" ng-model="num">
    <div>current scope: {{num}}</div>
</div>

Может ли кто-нибудь объяснить мне, почему входные данные являются неотредактированными /readonly? Если это по дизайну, какое обоснование?

ОБНОВЛЕНИЕ 2/20/2014

Похоже, это уже не проблема для v1.2.0 + Demo. Но имейте в виду, что, хотя пользовательские элементы управления теперь доступны для редактирования с новыми версиями angularJS, это свойство num в дочерних областях, а не в родительской области, которые изменяются. Другими словами, изменение значений в пользовательских элементах управления не влияет на массив myNumbers.

4b9b3361

Ответ 1

Может ли кто-нибудь объяснить мне, почему входные данные являются неотредактированными /readonly? Если это по дизайну, какое обоснование?

Это по дизайну от Angular 1.0.3. У Артема есть очень хорошее объяснение того, как 1.0.3+ работает, когда вы "привязываетесь к каждому элементу ng-repeat напрямую" – т.е.

<div ng-repeat="num in myNumbers">
  <input type="text" ng-model="num">

Когда ваша страница изначально отображается, вот изображение ваших областей (я удалил один из элементов массива, поэтому на картинке будет меньше коробок):

введите описание изображения здесь (нажмите, чтобы увеличить)

Пунктирные линии показывают прототипическое наследование области.
Серые линии показывают child → родительские отношения (т.е. какие ссылки $parent).
Коричневые линии показывают $$ nextSibling.
Серые ящики - это примитивные значения. Синие квадратики - это массивы. Фиолетовые объекты.

Обратите внимание, что ответ SO, который вы указали в комментарии, был написан до выхода 1.0.3. До 1.0.3 значения num в дочерних областях ngRepeat фактически изменились бы при вводе в текстовые поля. (Эти значения не будут видны в родительской области.) Начиная с версии 1.0, ngRepeat теперь заменяет значения ngRepeat scope num значениями (неизмененными) из массива scope/mainCtrl scope myNumbers во время цикла дайджеста. Это по сути делает исходные данные неизменными.

Исправлено использование массива объектов в вашем MainCtrl:

$scope.myNumbers = [ {value: 10}, {value: 20} ];

а затем привязывается к свойству value объекта в ngRepeat:

<div ng-repeat="num in myNumbers">
  <input type="text" ng-model="num.value">
  <div>current scope: {{num.value}}</div>

Ответ 2

Эта проблема теперь рассматривается более поздними версиями AngularJS с функцией track by, позволяющей повторителям по примитивам:

<div ng-repeat="num in myNumbers track by $index">
  <input type="text" ng-model="myNumbers[$index]">
</div>

Страница не будет перерисовываться после каждого нажатия клавиши, что решает проблему потерянного фокуса. Официальный документ AngularJS довольно смутно и смущает об этом.

Ответ 3

ngRepeat использует ссылку на исходный массив. Поскольку integer (Number in js) - это тип значения, а не ссылочный тип, поэтому не может быть передан по ссылке в javascript. Это изменение не будет распространено.

Вот демонстрация:

   var x = 10;
   var ox = {value:10};

   var y = x;
   var oy = ox;

   y = 15
   oy.value = 15;

Какими будут значения x и ox?

>> x = 10;
>> y = 15;
>> ox = {value:15};
>> oy = {value:15};

Все объекты javascript передаются по ссылке, и все примитивы передаются значением [ "string", "number" и т.д.].

Рабочий плункер http://plnkr.co/edit/7uG2IvAdC2sAEHbdHG58

Ответ 4

Кажется, что Angular не может написать модель, определенную таким образом. Используйте ссылку на начальный атрибут $scope, чтобы он правильно привязывал значение:

<div ng-repeat="num in myNumbers">
  <input type="text" ng-model="myNumbers[$index]">
</div>

Ответ 5

У меня была аналогичная проблема (а также была нужна функция "добавить" и "удалить" ) и решила проблему следующим образом:

$scope.topics = [''];
$scope.removeTopic = function(i) {
   $scope.topics.splice(i, 1); 
}

<div ng-repeat="s in topics track by $index">
    <input ng-model="$parent.topics[$index]" type="text">
    <a ng-click="removeTopic($index)">Remove</a>
</div>

<a ng-click="topics.push('new topic')">Add</a>