AngularJS: ng-repeat avec liste dynamique, sans reconstruire l'arborescence DOM entière?
J'utilise ng-repeat sur une ligne de table avec des données d'un tableau JSON récupérées à partir d'un serveur. Mon objectif est que la liste soit mise à jour automatiquement chaque fois qu'un élément est ajouté, supprimé ou modifié sur le serveur, sans affecter les éléments non modifiés. Dans l'implémentation finale, ces lignes de table contiendront également des liaisons bidirectionnelles <input>
et des <select>
éléments pour renvoyer les mises à jour au serveur. Certaines des options disponibles dans les <select>
éléments seront également générées à l'aide des directives ng-repeat d'une autre liste qui peut également changer.
Jusqu'à présent, chaque fois qu'un nouveau tableau provient du serveur (actuellement interrogé toutes les deux secondes), toute la liste ng-repeat est supprimée et régénérée. Ceci est problématique car cela interfère avec la sélection de texte, détruit les champs de saisie même s'ils sont actuellement modifiés par l'utilisateur et s'exécute probablement beaucoup plus lentement que nécessaire.
J'ai écrit d'autres applications Web qui font ce que je veux en utilisant jQuery et la manipulation DOM, mais le code finit par être vraiment poilu et le développement prend du temps. J'espère utiliser AngularJS et la liaison de données pour accomplir cela en une fraction du code et du temps.
Alors, voici la question: est-il possible de mettre à jour le tableau de sauvegarde de cette façon, mais de modifier uniquement les éléments DOM correspondant aux éléments / propriétés qui ont réellement changé?
Voici un cas de test minimal qui simule une interrogation périodique en utilisant un tableau codé en dur dans une minuterie (voir en direct sur http://jsfiddle.net/DWrmP/ ). Notez que la sélection de texte est effacée toutes les 500 ms en raison des éléments supprimés et recréés.
HTML
<body ng-app="myApp">
<table ng-controller="MyController">
<tr ng-repeat="item in items | orderBy:'id'">
<td>{{item.id}}</td>
<td>{{item.data}}</td>
</tr>
</table>
</body>
JavaScript
angular.module('myApp', []).controller(
'MyController', [
'$scope', '$timeout',
function($scope, $timeout) {
$scope.items = [
{ id: 0, data: 'Zero' }
];
function setData() {
$scope.items = [
{ id: 1, data: 'One' },
{ id: 2, data: 'Two' },
{ id: 5, data: 'Five' },
{ id: 4, data: 'Four' },
{ id: 3, data: 'Three' }
];
$timeout(setData, 500);
}
$timeout(setData, 500);
}
]
);
Pour ceux qui trouvent cela sur Google, la page ci-dessous décrit une fonctionnalité d'AngularJS 1.2 qui aide à résoudre ce problème:
http://www.bennadel.com/blog/2556-Using-Track-By-With-ngRepeat-In-AngularJS-1-2.htm
Modifier pour ajouter: les phrases les plus importantes de l'article lié, au cas où le lien mourrait:
Avec la nouvelle syntaxe «track by», je peux maintenant indiquer à AngularJS quelle propriété d'objet (ou chemin de propriété) doit être utilisée pour associer un objet JavaScript à un nœud DOM. Cela signifie que je peux échanger des objets JavaScript sans détruire les nœuds DOM tant que l'association "track by" fonctionne toujours.