Question Actualiser observableArray lorsque les éléments ne sont pas observables


Fondamentalement, j'ai un observableArray et les valeurs de chaque élément ne sont pas observables. Cela signifie que lorsque je modifie une valeur d'élément, l'interface utilisateur dans une boucle foreach de l'objet observableArray ne se met pas à jour en conséquence.

Cela signifie un changement massif si je dois les définir comme observables, alors est-il possible de rafraîchir manuellement l'interface utilisateur ou observableArray?


25
2017-11-05 12:02


origine


Réponses:


Oui, vous pouvez appeler valueHasMutated fonction pour votre tableau:

yourArray.valueHasMutated();

MODIFIER: Si d'abord ne vous a pas aidé, vous pouvez faire le rafraîchissement "sale":

self.refresh = function(){
    var data = self.array().slice(0);
    self.array([]);
    self.array(data);
};

Voici le violon de travail: http://jsfiddle.net/vyshniakov/FuEy6/2/


49
2017-11-05 12:05



Lorsque vous avez un tableau observable avec des éléments non observables et que certaines propriétés de l'un des éléments du tableau changent, si vous souhaitez actualiser uniquement cet élément, vous pouvez utiliser indexOf et splice, comme ça:

var changedIdx = obsArray.indexOf(changedItem);
obsArray.splice(changedIdx , 1); // removes the item from the array
obsArray.splice(changedIdx , 0, changedItem); // adds it back

Ce que cela fait, c'est de rechercher l'élément dans le tableau, de le supprimer et de le réinsérer. Lorsqu'il est réinséré, l'élément est lié à nouveau, avec les nouvelles valeurs.

Si vous aimez cette solution, vous pouvez étendre les fonctionnalités de toutes les baies observables, comme ceci:

ko.observableArray.fn.refresh = function (item) {
    var index = this['indexOf'](item);
    if (index >= 0) {
        this.splice(index, 1);
        this.splice(index, 0, item);
    }
}

Ensuite, lorsque vous modifiez un élément d'un tableau, vous devez simplement effectuer cet appel:

obsArray.refresh(changedItem);

Si vous avez de nombreux éléments dans votre tableau, vous obtiendrez une performance améliorée par rapport à la dirty Actualiser par Artem Vyshniakov, qui met à jour les liaisons pour tous les éléments du tableau, et pas seulement pour celui modifié.

Noter la valueHasMutated, à part être non documenté (et pour usage interne, je suppose), ne vérifie que si le tableau lui-même a changé, pas si les éléments non observables du tableau ont changé, donc cela ne fonctionne pas. C'est à dire. il ne détecte que si vous avez ajouté des éléments au tableau, supprimé des éléments du tableau, modifié des éléments du tableau avec de nouveaux éléments différents ou modifié l'ordre des éléments. Mais il ne vérifie pas si les éléments eux-mêmes ont changé


19
2018-01-26 13:11



J'ai fini par utiliser l'approche sale d'en haut, mais j'ai fait en sorte que toutes mes baies observables aient cette fonctionnalité.

ko.observableArray.fn.refresh = function () {
        var data = this().slice(0);
        this([]);
        this(data);
    };

Le valueHasMutated n'a pas fonctionné pour moi. Son genre de boiteux la liste entière doit être mise à jour. Ou dans mon cas, trouver un moyen d'étendre le plugin de cartographie ko pour remplir les tableaux observables avec des objets observables.


5
2017-09-22 19:49



J'ai trouvé une solution simple en remplaçant l'objet entier dans le tableau.

Dans cet exemple de paramètre ix est l'index, oLine est l'objet mis à jour et oVM.objProps.lines contient le tableau. La solution a fonctionné comme un champion.

/* This contortion causes the computed function to fire because
 * we have replaced the entire line object.
 */
function forceRefresh(ix,oLine) {
  var oVM = pme.getVM();
  oLine = JSON.parse(JSON.stringify(oLine));
  oVM.oObjProp.lines[ix] = oLine;
}

0
2017-10-26 08:05



J'utilise Knockout avec deferUpdates et la solution de JotaBe nécessite une mise à jour.

Il semble que Knockout détecte, lors de la suppression / de l'ajout, qu'il s'agit du même élément. Ne rafraîchissez donc pas le tableau.

J'ai adopté la solution suivante:

ko.observableArray.fn.refresh = function (item, index) {
    if (index==null) index = this['indexOf'](item);
    if (index >= 0) {
        this.splice(index, 1, ko.utils.extend({}, item)) // create new item
        //this.splice(index, 1);
        //this.splice(index, 0, item);
    }
}

et il rafraîchit le tableau correctement! :-)

Remarque J'ai ajouté un deuxième argument à la fonction de rafraîchissement, pour spécifier l'index lorsque l'index est donné, pour éviter de lancer indexOf.


0
2018-05-22 13:52