2017-06-08 3 views
0

J'ai créé une liaison personnalisée knockout pour envelopper tag-it basé sur le proposal de Droyad. Le code final (simplifié) est:Boucle infinie pour tag-it enveloppé dans un composant knock-out

ko.bindingHandlers.tagit = { 
    init: function (element, valueAccessor, allBindingsAccessor) { 
     var bind = function() { 
      valueAccessor().tagsList($(element).tagit("assignedTags")); 
     }; 

     var options = $.extend({ 
      afterTagAdded: bind, 
      afterTagRemoved: bind 
     }, valueAccessor().options || {}); 

     // Create tags editor 
     $(element).tagit(options); 

     ////// Block 1 
     var value = ko.utils.unwrapObservable(valueAccessor()); 
     var tags = value.tagsList(); 
     for(var x = 0; x < tags.length; x++) { 
      $(element).tagit("createTag", tags[x]); 
     } 
     ////// End Block 1 
    }, 
    ////// Block 2 
    update: function (element, valueAccessor, allBindingsAccessor) { 
     var value = ko.utils.unwrapObservable(valueAccessor()); 
     var tags = value.tagsList(); 
     $(element).tagit("removeAll"); 
     for(var x = 0; x < tags.length; x++) { 
      $(element).tagit("createTag", tags[x]); 
     } 
    } 
    ////// End Block 2 
}; 

Le code HTML correspondant est:

<div data-bind="with: currentDocument"> 
    <input data-bind="tagit: {tagsList: tags}"></input> 
</div> 

Mon problème: je dois utiliser "Block 1" et supprimer "Block 2" sinon le composant entrer dans un infini boucle. Sans bloc 2, tag-it affiche les tags à chaque fois que je change de document (currentDocument change) et je peux éditer manuellement les tags sans problèmes. Au lieu de cela, si je change currentDocument.tags par programme, la modification n'est pas visualisée (évidemment). Si je supprime le bloc 1 et ajoute le bloc 2, le rappel afterTagAdded se déclenche pour chaque balise ajoutée, ce qui modifie à son tour le tableau de balises, qui déclenche la fonction de mise à jour, etc.

Une idée sur la façon de résoudre le problème? Je pense que si les callbacks afterTagAdded et afterTagRemoved ne se déclenchent que pour les modifications manuelles et non pour $ (element) .tagit ("createTag", tags [x]); le problème pourrait être résolu. Merci pour votre aide!

+0

Il semble que vous ne deviez pas supprimer et recréer toutes les étiquettes, mais seulement enlever celles qui ne devraient pas être là et ajouter celles qui devraient. –

Répondre

0

La solution est simple mais pas élégante. J'ai défini une variable "loading" qui est définie sur true lorsque la modification est provoquée par le chargement de l'éditeur de tags. Lorsque true bloque la mise à jour observable. (Dans le code précédent, supprimez le bloc 1 et ajoutez le bloc 2).

En essayant d'expliquer le problème sur SO, comme d'habitude, aidez-moi à trouver une solution. Merci aussi pour ça!

ko.bindingHandlers.tagit = { 
    loading: false, 
    init: function (element, valueAccessor, allBindingsAccessor) { 
     var bind = function() { 
      if(ko.bindingHandlers.tagit.loading) return; 
      valueAccessor().tagsList($(element).tagit("assignedTags")); 
     }; 
     ... 
    }, 
    update: function (element, valueAccessor, allBindingsAccessor) { 
     // Load data 
     ko.bindingHandlers.tagit.loading = true; 
     var value = ko.utils.unwrapObservable(valueAccessor()); 
     var tags = value.tagsList(); 
     $(element).tagit("removeAll"); 
     for(var x = 0; x < tags.length; x++) { 
      $(element).tagit("createTag", tags[x]); 
     } 
     ko.bindingHandlers.tagit.loading = false; 
    }