web-dev-qa-db-fra.com

Passage de paramètre en utilisant onclick ou une liaison par clic avec KnockoutJS

J'ai cette fonction:

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

J'avais l'habitude de faire cela avec JavaScript et HTML brut:

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

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

51
BlaShadow

Si vous configurez une liaison de clic dans Knockout, l'événement est passé en tant que 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 démontre: 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 en tant que premier paramètre. Sur init, vous pouvez attacher votre propre gestionnaire d’événements click pour effectuer les actions de votre choix.

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());
31
John Earles

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);
    };
}();
80
Juliano Sales

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

26
Salvador Dali

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

Pas une réponse directe à la question telle qu'elle a été posée, mais probablement une réponse à la question de la plupart des Googlers qui atterrissent ici ont: utilisation la click liaison 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 à propos de la réelle question ... *

La question actuelle a un bit intéressant:

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

Ne fais pas ça! Ne modifiez pas le DOM de cette façon lorsque vous utilisez un framework MVVM tel que KnockoutJS, en particulier le morceau du DOM qui est votre propre parent. Si vous voudriez faites cela, le bouton disparaîtrait (si vous remplacez le innerHTML de votre parent, vous serez parti pour toujours!).

Au lieu de cela, modifiez le View Model dans votre gestionnaire, et choisissez la vue respond. 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>
12
Jeroen

La documentation de Knockout mentionne également un moyen beaucoup plus simple de passer des paramètres supplémentaires à des fonctions liées à l'aide d'un on-click liaison en utilisant function.bind comme ceci:

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