41 votes

Lier les entrées à un tableau de primitives en utilisant ngRepeat => entrées non éditables

Voici un démo à mon problème.

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

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

Quelqu'un peut-il m'expliquer pourquoi les entrées ne sont pas modifiables et ne sont pas accessibles en lecture seule ? S'il s'agit d'une conception, quelle en est la raison ?

MISE À JOUR 2/20/2014

Il semble que ce problème ne se pose plus pour la version 1.2.0+. Démonstration . Mais gardez à l'esprit que, bien que les contrôles utilisateur soient désormais modifiables avec les nouvelles versions d'angularJS, c'est le contrôle de l'utilisateur qui est le plus important. num dans la propriété champs d'application pour les enfants et non la portée parentale, qui sont modifiées. En d'autres termes, la modification des valeurs dans les contrôles utilisateur n'affecte pas la portée parentale. myNumbers de la gamme.

67voto

Mark Rajcok Points 85912

Quelqu'un peut-il m'expliquer pourquoi les entrées ne sont pas modifiables et ne sont pas accessibles en lecture seule ? Si c'est à dessein, quelle en est la raison ?

C'est un choix délibéré, à partir d'Angular 1.0.3 . Artem a un très bonne explication de la façon dont la version 1.0.3+ fonctionne lorsque vous "liez chaque élément ng-repeat directement" - c'est-à-dire,

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

Lorsque votre page s'affiche initialement, voici une image de vos champs d'application (j'ai supprimé l'un des éléments du tableau, afin que l'image comporte moins de cases) :

enter image description here (cliquer pour agrandir)

Les lignes en pointillé montrent un prototype d'héritage de portée.
Les lignes grises indiquent les relations enfant → parent (c'est-à-dire, ce que l'on peut dire de l'enfant). $parent références).
Les lignes brunes indiquent $$nextSibling.
Les cases grises correspondent à des valeurs primitives. Les cases bleues sont des tableaux. Les cases violettes sont des objets.

Notez que la réponse de mon SO que vous avez référencée dans un commentaire a été écrite avant la sortie de la version 1.0.3. Avant la version 1.0.3, le num dans les champs d'application enfants ngRepeat changeraient réellement lorsque vous taperiez dans les zones de texte. (Depuis la version 1.0.3, ngRepeat remplace désormais la portée ngRepeat num avec les valeurs (inchangées) de la portée parent/MainCtrl myNumbers au cours d'un cycle de digestion. Cela rend essentiellement les entrées non modifiables.

La solution consiste à utiliser un tableau d'objets dans votre MainCtrl :

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

puis de se lier à la value de l'objet dans le ngRepeat :

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

33voto

sebnukem Points 432

Ce problème est désormais résolu par les versions plus récentes d'AngularJS avec la fonction track by qui autorise les répétitions sur les primitives :

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

La page ne sera pas repeinte après chaque frappe, ce qui résout le problème de la perte de focus. La documentation officielle d'AngularJS est assez vague et confuse à ce sujet.

9voto

Umur Kontacı Points 12524

NgRepeat utilise un référence au tableau source. Puisque integer (Number in js) est un valeur et non un référence et ne peut donc pas être passé par référence en javascript. La modification ne sera pas propagée.

Voici une démonstration :

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

   var y = x;
   var oy = ox;

   y = 15
   oy.value = 15;

Quelles seraient les valeurs de x y ox ?

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

Tous les objets javascript sont transmis par référence et toutes les primitives sont transmises par valeur ["string", "number", etc].

Plongeur en activité http://plnkr.co/edit/7uG2IvAdC2sAEHbdHG58

9voto

Dmitry Evseev Points 4973

Il semble qu'Angular ne soit pas capable d'écrire dans un modèle défini de cette manière. Utilisez une référence à l'attribut $scope initial pour lui permettre de lier la valeur de la bonne manière :

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

9voto

aidan Points 2496

J'ai rencontré un problème similaire (et j'avais également besoin des fonctionnalités "ajouter" et "supprimer"), et j'ai résolu le problème de la manière suivante :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X