2017-06-30 1 views
2

violon soutien: https://jsfiddle.net/lezhnev_dmitriy/5Lvq1nra/instances de composants multiples pour rappel remplace liaison personnalisée

$(function(){ 
 

 
// when DOM ready 
 

 
ko.bindingHandlers.button = { 
 
    init: function (element, valueAccessor, allBindings) { 
 
        this.onClick = valueAccessor(); 
 
        $(element).html('<button data-bind="click: onClick">Click</button>'); 
 
       }, 
 
    update: function (element, valueAccessor, allBindings) { 
 
       }, 
 
}; 
 

 
ko.components.register('comp1', { 
 
\t template: '<div>component instance <span data-bind="text: instance_id"></span> <span data-bind="button: handleClick"></span></div>', 
 
    viewModel: function() { 
 
    var self = this; 
 
    self.instance_id = ko.observable(Math.round(Math.random() * 1000)); // debug purpose 
 

 
    self.handleClick = function() { 
 
     alert('clicked at ' + self.instance_id()); 
 
    }.bind(this); // very interesting hint! 
 
    } 
 
}); 
 

 
ko.applyBindings(); 
 

 

 
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 
<comp1></comp1> 
 
<comp1></comp1>

J'ai deux composants et chaque INJECTE de liaison personnalisée (button) dans son modèle. Ensuite, il attache un rappel à cette liaison. Mais seule la dernière liaison fonctionne (les deux boutons sont désormais gérés via la dernière instance de composant).

Ai-je raté quelque chose?

MISE À JOUR: Je trouve que ce code fonctionne réellement

ko.bindingHandlers.button = { 
 
       init: function (element, valueAccessor, allBindings) { 
 
        var self = this; 
 
        self.onClick = valueAccessor(); 
 
        $(element).html('<button>Click</button>'); 
 
        $('button', element).click(self.onClick); 
 
       }, 
 
       update: function (element, valueAccessor, allBindings, viewModel_deprecated, bindingContext) { 
 
        var self = this; 
 

 
       }, 
 
      }; 
 

 
      ko.components.register('comp1', { 
 
       template: '<div>component instance <span data-bind="text: instance_id"></span> <span data-bind="button: handleClick"></span></div>', 
 
       viewModel: function() { 
 
        var self = this; 
 
        self.instance_id = ko.observable(Math.round(Math.random() * 1000)); // debug purpose 
 

 
        self.handleClick = function() { 
 
         console.log('clicked at ' + self.instance_id()); 
 
        }.bind(this); // very interesting hint! 
 
       } 
 
      }); 
 
      
 
ko.applyBindings();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 

 
<comp1></comp1> 
 
<comp1></comp1>

+0

J'ai trouvé cette solution de contournement: https://github.com/knockout/knockout/issues/2263 –

+0

essayez d'utiliser la fonction createViewModel, j'ai eu 0 problème en utilisant cela. – Shadowfox

+1

J'ai essayé moi-même, même problème. Je pense que le problème vient de l'ajout d'éléments DOM par code dans le bindingHandler. Vous êtes censé utiliser des modèles pour cela, je suppose. Fiddle: https://jsfiddle.net/5Lvq1nra/2/ – Shadowfox

Répondre

1

À mon avis, vous n'êtes pas censé changer les noeuds DOM du code d'un bindingHandler. Nous avons des modèles pour cette raison.

<script id="buttonTemplate" type="text/html"> 
    <button data-bind="click: handleClick">Click</button> 
</script>  

template: '<div>component instance <span data-bind="text: instance_id"></span> <span data-bind="template: {name: \'buttonTemplate\', data: $data }"></span></div>', 

J'ai mis à jour votre violon: https://jsfiddle.net/5Lvq1nra/2/

Edit: transmettre les données de $ dans la propriété de données d'un modèle est pas vraiment nécessaire (par défaut), juste pour montrer que vous pouvez passer un objet en tant que modèle.

+0

Je pense que ce modèle ne correspond pas à mon cas. Quoi qu'il en soit, laissez-moi vous dire ce que j'ai et peut-être vous pouvez me conseiller un meilleur moyen? J'ai un SPA qui peut avoir plusieurs pages. Chaque page est alimentée par un composant knock-out (recherche de filtre en haut et les résultats en bas). Filtre de recherche alimenté par la liaison personnalisée. Ainsi, le composant injecte le widget de recherche dans son modèle et transmet le rappel pour être averti lorsque la recherche est lancée. Le widget lui-même est suffisamment complexe pour être un bon candidat pour une liaison personnalisée avec des événements html et DOM personnalisés. Est-ce que cela a du sens pour vous? –