2012-04-06 8 views
45

Ich habe diese Funktion Passing Onclick oder ein Klick Bindung:Parameter mit KnockoutJS

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

ich früher tat dies mit einfacher JavaScript und HTML:

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

Wie kann ich das idiomatischen mit knockout.js?

Antwort

28

Wenn Sie eine Klickbindung in Knockout einrichten, wird das Ereignis als zweiter Parameter übergeben. Sie können das Ereignis verwenden, um das Element abzurufen, auf dem der Klick ausgeführt wurde, und die gewünschte Aktion ausführen.

Hier ist eine Geige, die zeigt: Alternativ http://jsfiddle.net/jearles/xSKyR/

, könnten Sie Ihre eigene individuelle Bindung erstellen, die das Element empfangen wird es als ersten Parameter gebunden ist. Bei der Initialisierung können Sie Ihren eigenen Click-Event-Handler anhängen, um alle gewünschten Aktionen auszuführen.

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()); 
73

Verwenden eine Bindung, wie in diesem Beispiel:

<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); 
    }; 
}(); 
+2

jsfiddle Version : http://jsfiddle.net/fiddleSt1ck5/agjt6/ – fiat

+0

Danke. Aber was, wenn ich mehr als einen Parameter übergeben möchte? Wie würde ich das tun? – sudip

+1

@sudip Einfach: klicken: PesquisaGerente.bind ($ data, '1', '2', '3') – pimbrouwers

22

Ich weiß, das ist eine alte Frage, aber hier ist mein Beitrag. Statt all dieser Tricks können Sie einfach eine Funktion in eine andere Funktion einfügen.

<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()); 

Und hier ist die fiddle

+0

Ich mag dieses am meisten. Einfach und leicht zu verstehen. Es endete damit, dass man überhaupt keine Parameter übergeben musste, aber trotzdem plante, diese Methode zu verwenden (und zum Testen zu verwenden). – Cody

+0

Dies ist in Ordnung, aber * this * für die aufgerufene Funktion referenziert das Fenster anstelle des ViewModels, das typischerweise in KO-gebundenen Funktionen erwartet wird. function.bind ($ data) löst dieses Problem unter anderem. – hemp

+1

Erstellen von Funktion im Bindungskörper sieht seltsam aus, ich würde für Bind-Methode gehen. –

7

Eine generische Antwort auf wie click Ereignisse mit KnockoutJS zu handhaben ...

nicht eine gerade nach oben Antwort auf die Frage: Wie ich hier getan habe Wie gesagt, aber wahrscheinlich eine Antwort auf die Frage, die die meisten Googler hier haben: benutze the click binding from KnockoutJS statt onclick. Wie folgt aus:

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>


** Eine Notiz über die tatsächlichen Frage ... *

Die eigentliche Frage hat eine interessante Bit:

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

Tun Sie das nicht! Ändern Sie das DOM nicht so, wenn Sie ein MVVM-Framework wie KnockoutJS verwenden, insbesondere nicht das Teil des DOM, das Ihr eigenes Elternelement ist. Wenn Sie würde dies tun, würde die Schaltfläche verschwinden (wenn Sie ersetzen Ihre Eltern innerHTML Sie selbst werden für immer verschwunden sein!).

Stattdessen ändern die Ansicht Modell in Ihrem Handler statt, und die Ansicht reagieren. Zum Beispiel:

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>

3

auch Knockout in der Dokumentation eine viel sauberere Möglichkeit der Weitergabe zusätzliche Parameter an Funktionen erwähnt eine on-click Bindung mit function.bind wie diese gebunden mit:

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