2013-10-01 1 views
0

En raison du chargement des données via AJAX, mes données doivent être mises à jour à l'arrivée des données.Ko: mise à jour de la fonction calculée deux fois

Lors du chargement de la page, je collecte des projets dans la base de données. Chargez ensuite les données pour les tâches et les tags en fonction du projet sélectionné (self.SelectedProject).

self.Projects = ko.observableArray(); 
self.Tasks = ko.observableArray(); 
self.Tags = ko.observableArray(); 
self.SelectedProject = ko.observable(); // Chosen Project-object... 

Pour l'initialisation je charge les données pour le premier projet:

self.SelectedProject(self.Projects()[0]);   // Choose first returned Project... 

Puis-je continuer à remplir mes tableaux d'étiquettes-aide:

ko.computed(function() { 
    // must be ko.computed as else will not update when data arrives for Tags and Tasks (which are likely to be empty at load time)... 

    // Empty projectAvailableTags before refill... 
    self.SelectedProject().projectAvailableTags([]); 

    // First populate current project's "projectAvailableTags"-array with values... 
    for (var j = 0, jlen = self.Tags().length; j < jlen; j++) { 
     self.SelectedProject().projectAvailableTags().push(self.Tags()[j].TagName()); 
    } 

    for (var i = 0, ilen = self.Tasks().length; i < ilen; i++) { 
     //---- Populate each TaskTag-array with Tags... 
     for (var j = 0, jlen = self.Tags().length; j < jlen; j++) { 
      if (self.Tags()[j].TagTaskId() === self.Tasks()[i].TaskId) { 
       self.Task()[i].TaskTags.push(self.Tags()[j]); 
       // Populate the different tag-Arrays... 
       var tagtype = self.Tags()[j].TagType; 
       switch (tagtype()) { 
        case 0: self.Tasks()[i].Location().push(self.Tags()[j].TagName()); break; 
        case 1: self.Tasks()[i].Manager().push(self.Tags()[j].TagName()); break; 
        case 2: self.Tasks()[i].Employee().push(self.Tags()[j].TagName()); break; 

       } 
      } 
     } 

    }; 
}); 

Ce regard probablement étrange et peut-être que je Je le fais inutilement compliqué. J'utilise http://aehlke.github.com/tag-it/ en tant que gestionnaire de balises et il nécessite uniquement un tableau avec des balises. Ainsi, je n'ai pas compris comment utiliser le tableau Tags() directement, même si je suis comme ça.

Les tâches sont présentées dans un accordéon, et je veux les tâches balises à appliquer dans le panneau de contenu, alors que j'utiliser mes projets-tags comme tagSource pour autocomplete fonctionnalité ...

Mais je ne peux pas comprendre pourquoi mes balises sont appliquées 2 fois avec le ko.computed alors qu'elles ne sont pas appliquées à moins que je resélectionne le projet sans cela.

Répondre

1

Je pense que vous manquez un peu le point des observables calculés. La seule vraie distinction entre les observables calculés et une fonction régulière est que vous pouvez lier à une observable calculée et vous y fier pour une mise à jour automatique chaque fois que l'un de ses composants change.

Le example in the knockout documentation pour les observables calculés utilise Prénom/Nom, ce qui est un bon exemple. Sur la base de cela, ce n'est vraiment pas une bonne idée de mettre à jour la dépendance d'un calcul dans celui calculé lui-même. Dans la version précédente de knockout, cela aurait effectivement créer une référence circulaire infinie. Je suppose que le calcul est en cours d'exécution deux fois car les Tags et les Tâches reçoivent tous deux de nouvelles données, ce qui déclenche une mise à jour (mais une seule mise à jour en raison des sauvegardes intégrées dans KO).

Une meilleure option serait de s'abonner à SelectedProject. Ensuite, chaque fois que des changements observables, vous pouvez re-racker tous vos tableaux.

self.SelectedProject.subscribe(function(newValue) { 
    <load your arrays here> 
}); 
+0

Merci de l'avoir clarifié. J'ai toujours un problème, car le fichier "SelectedProject.subscribe" ne se déclencherait pas lors de la première instanciation de mon ViewModel, n'est-ce pas? J'ai besoin de faire fonctionner mes for-loops après que l'AJAX ait retourné des valeurs pour Tasks and Tags. Comme c'est le cas maintenant, je les mets à jour avec une fonction d'abonnement, mais j'ai aussi besoin de ces tableaux avant de sélectionner un nouveau projet. –

+0

Je voudrais abstrait de la logique de chargement de tableau dans une méthode distincte, puis l'appeler pour le SelectedProject.subscribe et également dans votre rappel pour votre demande AJAX. – Jared

+0

Merci Jared! Je reçois d'abord les balises (pour le projet donné) avec un $ .getJSON ("/ myService/GetAllTag", "projectid =" + tp.ProjectId, fonction (allData) {/ * résultat de mappage à Tags-array * /} Est-ce que vous appelez le getJSON pour les tâches dans le rappel pour Tags? J'ai besoin à la fois des balises et des tâches pour la logique de chargement de la baie Je vous comprends que je devrais faire quelque chose comme: $.getJSON ("/ myService/GetAllTag", "projectid =" + tp.ProjectId, fonction (adata) {mapTags(); $ .getJSON ("/ monService/GetAllTasks", "projectid =" + tp.ProjectId, fonction (bdata) {mapTasks(); loadArray(); }) –

Questions connexes