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