web-dev-qa-db-fra.com

AngularJS: ng-repeat avec liste dynamique, sans reconstruire la totalité de l'arborescence DOM?

J'utilise ng-repeat sur une ligne d'un tableau avec les données d'un tableau JSON récupéré 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 la dernière implémentation, ces lignes de table contiendront également des éléments <input> et <select> liés de manière bidirectionnelle pour renvoyer les mises à jour au serveur. Certaines des options disponibles dans les éléments <select> seront également générées à l'aide de directives ng-repeat d'une autre liste pouvant également changer.

Jusqu'ici, 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 il interfère avec la sélection du texte, détruit les champs de saisie même s'ils sont en cours de modification 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 très complexe et le développement prend beaucoup de 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 uniquement de modifier les éléments DOM correspondant aux éléments/propriétés qui ont réellement changé?


Voici un scénario de test minimal qui simule une interrogation périodique à l'aide d'un tableau codé en dur dans une minuterie (à voir en direct à 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);
        }
        ]
);
32
nitrogen

Pour ceux qui trouvent cela sur Google, la page ci-dessous décrit une fonctionnalité dans 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 "piste par", je peux maintenant dire à 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 "piste par" fonctionne toujours.

36
dasho

Je crois que cet article explique le fonctionnement de ngRepeat 

http://www.bennadel.com/blog/2443-Rendering-DOM-Elements-With-ngRepeat-In-AngularJS.htm

Donc, si vous gardez des objets dans la collection - alors oui (i e $ hashKey persistent) 

Sinon - non

7
vittore

Je prévois de créer moi-même la solution suivante, même si elle figure toujours dans mon carnet de produit.

Le problème avec ng-repeat est qu’il supprimera des éléments du DOM quand il le faudra pour un tableau, cela voudrait dire qu’il sera redimensionné, etc., mais si les données sont dynamiques, elles risquent de scintiller car les données ont changé et la taille du tableau. est en train de changer. En particulier pendant la pagination, car toute la page n'a peut-être pas encore été chargée.

Pour éviter ce scintillement, la table ne doit pas changer le nombre de lignes. A la place, répétez ng des données "affichées" et modifiez-les au besoin, sans ajouter ni supprimer d'éléments du tableau.

0
Archimedes Trajano