54 votes

Passage de paramètres à l'aide de onclick ou d'une liaison par clic avec KnockoutJS

J'ai cette fonction :

function make(place)
{
  place.innerHTML = "somthing"
}

J'avais l'habitude de faire ça avec du simple JavaScript et du HTML :

<button onclick="make(this.parent)">click me</button>

Comment puis-je faire cela en utilisant l'idiomatique knockout.js ?

88voto

Juliano Sales Points 351

Utilisez une liaison, comme dans cet exemple :

<a href="#new-search" data-bind="click:SearchManager.bind($data,'1')">
  Search Manager
</a>

var ViewModelStructure = function () {
    var self = this;
    this.SearchManager = function (search) {
        console.log(search);
    };
}();

33voto

John Earles Points 4932

Si vous configurez une liaison par clic dans Knockout, l'événement est transmis comme deuxième paramètre. Vous pouvez utiliser l'événement pour obtenir l'élément sur lequel le clic s'est produit et effectuer l'action que vous souhaitez.

Voici un violon qui en fait la démonstration : http://jsfiddle.net/jearles/xSKyR/

Vous pouvez également créer votre propre liaison personnalisée, qui recevra l'élément auquel elle est liée comme premier paramètre. Lors de l'init, vous pouvez attacher votre propre gestionnaire d'événement de clic pour effectuer les actions que vous souhaitez.

http://knockoutjs.com/documentation/custom-bindings.html

HTML

<div>
    <button data-bind="click: clickMe">Click Me!</button>
</div>

Js

var ViewModel = function() {
    var self = this;
    self.clickMe = function(data,event) {

      var target = event.target || event.srcElement;

      if (target.nodeType == 3) // defeat Safari bug
        target = target.parentNode;

      target.parentNode.innerHTML = "something";
    }
}

ko.applyBindings(new ViewModel());

28voto

Salvador Dali Points 11667

Je sais que c'est une vieille question, mais voici ma contribution. Au lieu de toutes ces astuces, vous pouvez simplement envelopper une fonction dans une autre fonction. Comme je l'ai fait ici :

<div data-bind="click: function(){ f('hello parameter'); }">Click me once</div>
<div data-bind="click: function(){ f('no no parameter'); }">Click me twice</div>

var VM = function(){
   this.f = function(param){
     console.log(param);
   }
}
ko.applyBindings(new VM());

Et voici le violon

12voto

Jeroen Points 10696

Une réponse générique sur la façon de traiter click événements avec KnockoutJS...

Ce n'est pas une réponse directe à la question telle qu'elle a été posée, mais probablement une réponse à la question que se posent la plupart des Googlers qui atterrissent ici : utilisez le site click liaison à partir de KnockoutJS au lieu de onclick . Comme ça :

function Item(parent, txt) {
  var self = this;

  self.doStuff = function(data, event) {
    console.log(data, event);
    parent.log(parent.log() + "\n  data = " + ko.toJSON(data));
  };

  self.doOtherStuff = function(customParam, data, event) {
    console.log(data, event);
    parent.log(parent.log() + "\n  data = " + ko.toJSON(data) + ", customParam = " + customParam);
  };

  self.txt = ko.observable(txt);
}

function RootVm(items) {
  var self = this;

  self.doParentStuff = function(data, event) {
    console.log(data, event);
    self.log(self.log() + "\n  data = " + ko.toJSON(data));
  };

  self.items = ko.observableArray([
    new Item(self, "John Doe"),
    new Item(self, "Marcus Aurelius")
  ]);
  self.log = ko.observable("Started logging...");
}

ko.applyBindings(new RootVm());

.parent { background: rgba(150, 150, 200, 0.5); padding: 2px; margin: 5px; }
button { margin: 2px 0; font-family: consolas; font-size: 11px; }
pre { background: #eee; border: 1px solid #ccc; padding: 5px; }

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>

<div data-bind="foreach: items">
  <div class="parent">
    <span data-bind="text: txt"></span><br>
    <button data-bind="click: doStuff">click: doStuff</button><br>
    <button data-bind="click: $parent.doParentStuff">click: $parent.doParentStuff</button><br>
    <button data-bind="click: $root.doParentStuff">click: $root.doParentStuff</button><br>
    <button data-bind="click: function(data, event) { $parent.log($parent.log() + '\n  data = ' + ko.toJSON(data)); }">click: function(data, event) { $parent.log($parent.log() + '\n  data = ' + ko.toJSON(data)); }</button><br>
    <button data-bind="click: doOtherStuff.bind($data, 'test 123')">click: doOtherStuff.bind($data, 'test 123')</button><br>
    <button data-bind="click: function(data, event) { doOtherStuff('test 123', $data, event); }">click: function(data, event) { doOtherStuff($data, 'test 123', event); }</button><br>
  </div>
</div>

Click log:
<pre data-bind="text: log"></pre>

**Une note concernant le réel question...*

La question actuelle comporte un élément intéressant :

// Uh oh! Modifying the DOM....
place.innerHTML = "somthing"

Ne faites pas ça ! Ne modifiez pas le DOM de cette façon lorsque vous utilisez un framework MVVM comme KnockoutJS, et surtout pas la partie du DOM qui est votre propre parent. Si vous serait faire cela, le bouton disparaîtrait (si vous remplacez votre parent innerHTML toi-même, tu disparaîtras à jamais !).

Au lieu de cela, modifiez le Voir le modèle dans votre gestionnaire à la place, et faites en sorte que la vue répondre à . Par exemple :

function RootVm() {
  var self = this;
  self.buttonWasClickedOnce = ko.observable(false);
  self.toggle = function(data, event) {
    self.buttonWasClickedOnce(!self.buttonWasClickedOnce());
  };
}

ko.applyBindings(new RootVm());

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>

<div>
  <div  data-bind="visible: !buttonWasClickedOnce()">
    <button data-bind="click: toggle">Toggle!</button>
  </div>
  <div data-bind="visible: buttonWasClickedOnce">
    Can be made visible with toggle...
    <button data-bind="click: toggle">Untoggle!</button>
  </div>
</div>

5voto

gazubi Points 551

La documentation de Knockout mentionne également une manière beaucoup plus propre de passer des paramètres supplémentaires aux fonctions liées à l'aide d'un fichier de type on-click en utilisant function.bind comme ceci :

<button data-bind="click: myFunction.bind($data, 'param1', 'param2')">
    Click me
</button>

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