74 votes

S'abonner au tableau d'observables pour les entrées nouvelles ou supprimées uniquement

Donc oui, je peux m'abonner à un tableau observable :

vm.myArray = ko.observableArray();
vm.myArray.subscribe(function(newVal){...});

Le problème est le suivant newVal passé à la fonction est le tableau entier. Est-il possible d'obtenir uniquement la partie delta ? Disons que le ajouté o supprimé élément ?

123voto

Judah Himango Points 27365

La nouvelle version de KnockoutJS 3.0 comprend une fonction arrayChangement d'option d'abonnement sur ko.observableArray.

var myArray = ko.observableArray(["Alpha", "Beta", "Gamma"]);

myArray.subscribe(function(changes) {

    // For this example, we'll just print out the change info
    console.log(changes);

}, null, "arrayChange");

myArray.push("newitem!");

Dans le callback ci-dessus, l'argument "changes" sera un tableau d'objets "change" comme ceci :

[ 
   { 
      index: 3, 
      status: 'added', 
      value: 'newitem!' 
   }
]

Pour votre problème spécifique, vous voulez être informé des nouveaux articles ou de ceux qui sont retirés. . Pour implémenter cela en utilisant Knockout 3, cela ressemblerait à ceci :

myArray.subscribe(function(changes) {

    changes.forEach(function(change) {
        if (change.status === 'added' || change.status === 'deleted') {
            console.log("Added or removed! The added/removed element is:", change.value);
        }
    });

}, null, "arrayChange");

7voto

MPavlak Points 150

Comme je n'ai pas trouvé d'informations à ce sujet ailleurs, je vais ajouter une réponse sur la façon d'utiliser cette fonction avec TypeScript.

La clé ici était d'utiliser l'interface KnockoutArrayChange comme TEvent pour subscribe. Si vous ne le faites pas, il essaiera d'utiliser l'autre subscribe (non générique) et se plaindra que le statut, l'index et la valeur n'existent pas.

class ZoneDefinition {
    Name: KnockoutObservable<String>;
}

class DefinitionContainer
{
    ZoneDefinitions: KnockoutObservableArray<ZoneDefinition>;
    constructor(zoneDefinitions?: ZoneDefinition[]){
        this.ZoneDefinitions = ko.observableArray(zoneDefinitions);
        // you'll get an error if you don't use the generic version of subscribe
        // and you need to use the KnockoutArrayChange<T> interface as T
        this.ZoneDefinitions.subscribe<KnockoutArrayChange<ZoneDefinition>[]>(function (changes) {
            changes.forEach(function (change) {
                if (change.status === 'added') {
                    // do something with the added value
                    // can use change.value to get the added item
                    // or change.index to get the index of where it was added
                } else if (change.status === 'deleted') {
                    // do something with the deleted value
                    // can use change.value to get the deleted item
                    // or change.index to get the index of where it was before deletion
                }
            });
        }, null, "arrayChange");
}

0voto

green Points 5032

J'utilise une approche similaire mais différente, en gardant la trace de l'instrumentation d'un élément dans l'élément lui-même :

myArray.subscribe(function(array){
  $.each(array, function(id, el) {
    if (!el.instrumented) {
      el.instrumented = true;
      el.displayName = ko.computed(function(){
        var fn = $.trim(el.firstName()), ln = $.trim(el.lastName());
        if (fn || ln) {
          return fn ? (fn + (ln ? " " + ln : "")) : ln;
        } else {
          return el.email();
        }
      })
    }
  });
})

Mais c'est vraiment fastidieux et le schéma se répète dans tout mon code.

-1voto

jjperezaguinaga Points 1480

Pas que je sache. Vous voulez savoir ce que je fais ? J'utilise une variable précédente pour contenir la valeur, quelque chose appelé selectedItem

vm.selectedItem = ko.observable({});
function addToArray(item) { vm.selectedItem(item); vm.myArray.push(item); }

Ainsi, lorsque quelque chose arrive à mon tableau d'observables, je sais quel élément a été ajouté.

vm.myArray.subscribe(function(newArray) { var addedItem = vm.selectedItem(item); ... }

C'est vraiment verbeux, et en supposant que votre tableau contienne plusieurs types de données, vous auriez besoin d'une sorte de drapeaux qui vous aiderait à savoir quoi faire avec vos variables enregistrées...

vm.myArray.subscribe(function(newArray) {
  if ( wasUpdated )
    // do something with selectedItem
  else
    // do whatever you whenever your array is updated
}

Une chose importante à noter est que vous pouvez savoir quel élément a été ajouté si vous savez si push o unshift a été utilisé. Il suffit de parcourir le dernier élément du tableau ou le premier et voilà.

-2voto

Rudy Points 9

Essayez vm.myArray().arrayChanged.subscribe(function(eventArgs))

Cela a la valeur ajoutée lorsqu'un élément est ajouté, et la valeur retirée lorsqu'un élément est retiré.

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