简体   繁体   中英

KnockoutJS custom binding calling click event during bind, not on click

I`m attempting to bind an observable array of people two a two column responsive layout with click events using knockoutjs.

I have created a custom binding called TwoCol that loops through the array, and appends nodes to the DOM to create my suggested layout, but the click events are giving me trouble when I try to apply them in a custom binding nested in a loop.

I have played with it quite a bit, and encountered all types of results, but where I`m at now is calling my ~click~ event during binding, rather than on click.

http://jsfiddle.net/5SPVm/6/

HTML:

<div data-bind="TwoCol: Friends" id="" style="padding: 20px">

JAVASCRIPT:

function FriendsModel() {
    var self = this;
    this.Friends = ko.observableArray();
    this.SelectedFriend = "";
    this.SetSelected = function (person) {
        alert(person);
        self.SelectedFriend = person;
    }
}
function isOdd(num) {
    return num % 2;
}
ko.bindingHandlers.TwoCol = {
    update: function (elem, valueAccessor) {
        var i = 0;
        var rowDiv;
        var vFriends = ko.utils.unwrapObservable(valueAccessor());
        $(elem).html('');
        while (i < vFriends.length) {
            //create row container every other iteration
            if (!isOdd(i)) {
                rowDiv = document.createElement("div");
                $(rowDiv).addClass("row-fluid");
                elem.appendChild(rowDiv);
            }
            //add column for every iteration
            var colDiv = document.createElement("div");
            $(colDiv).addClass("span6");
            rowDiv.appendChild(colDiv);
            //actual code has fairly complex button html here
            var htmlDiv = document.createElement("div");
            var htmlButton = vFriends[i]
            htmlDiv.innerHTML = htmlButton;
            colDiv.appendChild(htmlDiv);
            //i think i need to add the event to the template too?
            //$(htmlDiv).attr("data-bind", "click: { alert: $data }")
            //it seems that the SetSelected Method is called while looping
            ko.applyBindingsToDescendants(htmlDiv, { click: friends.SetSelected(vFriends[i]) });
            i++;
        }
        return { controlsDescendantBindings: true };
    }
}

var friends = new FriendsModel();
friends.Friends.push('bob');
friends.Friends.push('rob');
friends.Friends.push('mob');
friends.Friends.push('lob');
ko.applyBindings(friends);

I don't think you're using ko.applyBindingsToDescendants correctly. I admit I'm a little confused as to the meaning of some of the values in your code, so I may have interpreted something incorrectly.

Here's a fiddle where I think it's working the way you intended: http://jsfiddle.net/5SPVm/7/ http://jsfiddle.net/5SPVm/8/

Notice if manually control descendant bindings ( return { controlsDescendantBindings: true }; ), you need to set that up in the init callback, instead of update. The update callback is too late for that.

Quick rundown of the changes (edited) :

  1. Moved the controlsDescendantBindings into the init binding callback
  2. Added the necessary parameter names to the binding param list to access additional values.
  3. I re-enabled the html.attr call. Notice that now, because the binding context is set to the actual item, the SetSelected method doesn't exist at that level anymore, so it is necessary to use $parent.SetSelected .

      $(htmlDiv).attr("data-bind", "click: $parent.SetSelected") 
  4. Fixed the ko.applyBindingsToDescendants call. This method takes a binding context, which is created from the current binding context, and also takes the element to apply the binding to. You don't want to reapply the binding, which is why this whole thing needs to be in the init handler.

      var childBindingContext = bindingContext.createChildContext(vFriends[i]); ko.applyBindingsToDescendants(childBindingContext, colDiv); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM