J'essaie de permettre à l'utilisateur de modifier une liste d'éléments en utilisant ngRepeat
et ngModel
. ( Voir ce violon .) Cependant, les deux approches que j'ai essayées conduisent à un comportement bizarre: l'une ne met pas à jour le modèle et l'autre rend la forme floue sur chaque touche du bas.
Est-ce que je fais quelque chose de mal ici? N'est-ce pas un cas d'utilisation pris en charge?
Voici le code du violon, copié pour plus de commodité:
<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>
Un séjour sans faille
Cela semble être un problème contraignant.
Le conseil est ne pas lier aux primitives .
Votre ngRepeat
effectue une itération sur les chaînes d'une collection, alors qu'elle devrait itérer sur des objets. Pour résoudre votre problème
<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/
En utilisant Angular dernière version (1.2.1) et en suivant $index
. Ce problème est résolu
<div ng-repeat="(i, name) in names track by $index">
Value: {{name}}
<input ng-model="names[i]">
</div>
Vous entrez dans une situation difficile lorsqu'il est nécessaire de comprendre comment scopes , ngRepeat et ngModel avec NgModelController . Essayez également d'utiliser la version 1.0.3. Votre exemple fonctionnera un peu différemment.
Vous pouvez simplement utiliser la solution fournie par jm-
Mais si vous voulez traiter la situation plus profondément, vous devez comprendre:
Comment votre exemple "Lier directement à chaque élément" fonctionne pour AngularJS 1.0.3:
'f'
en entrée;ngModelController
modifie le modèle pour la portée de l'élément (le tableau de noms n'est pas modifié) => name == 'Samf'
, names == ['Sam', 'Harry', 'Sally']
;$digest
est lancée;ngRepeat
remplace la valeur du modèle de la portée de l'élément ('Samf'
) par la valeur du tableau des noms inchangés ('Sam'
);ngModelController
render les entrées avec la valeur réelle du modèle ('Sam'
).Comment votre exemple "Indexation dans le tableau" fonctionne:
'f'
en entrée;ngModelController
change l'élément dans les noms array
=> `noms == ['Samf', 'Harry', 'Sally'];ngRepeat
ne trouve pas 'Samf'
dans le cache;ngRepeat
crée une nouvelle portée, ajoute un nouvel élément div avec une nouvelle entrée (c’est pourquoi le champ d’entrée perd son focus - l’ancien div avec l’ancienne entrée est remplacé par un nouveau div avec une nouvelle entrée);En outre, vous pouvez essayer d'utiliser AngularJS Batarang et voir comment modifie $ id de l'étendue de div avec l'entrée dans laquelle vous entrez.
Si vous n'avez pas besoin que le modèle soit mis à jour à chaque frappe de touche, liez-vous simplement à name
, puis mettez à jour l'élément de tableau lors de l'événement de flou:
<div ng-repeat="name in names">
Value: {{name}}
<input ng-model="name" ng-blur="names[$index] = name" />
</div>
Je viens de mettre à jour AngularJs à 1.1.2 et je n’ai aucun problème avec ça. Je suppose que ce bug a été corrigé.
http://ci.angularjs.org/job/angular.js-pete/57/artifact/build/angular.js
Le problème semble être lié à la façon dont ng-model
fonctionne avec input
et écrase l'objet name
, le rendant ainsi perdu pour ng-repeat
.
Pour contourner le problème, vous pouvez utiliser le code suivant:
<div ng-repeat="name in names">
Value: {{name}}
<input ng-model="names[$index]">
</div>
J'espère que ça aide
J'ai essayé la solution ci-dessus pour mon problème à cela a fonctionné comme un charme. Merci!
http://jsfiddle.net/leighboone/wn9Ym/7/
Voici ma version de cela:
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.models = [{
name: 'Device1',
checked: true
}, {
name: 'Device1',
checked: true
}, {
name: 'Device1',
checked: true
}];
}
et mon 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>