Knockout custom binding handler

2019-07-16 14:01发布

I am having trouble getting this to work: http://jsfiddle.net/2jg2F/1/

I basically want to make a link that changes to an input box when someone clicks on the text. I have tried knockout 2.0 and 2.1.

HTML

<div data-bind="clickToEdit : message"> </div>

Javascript

ko.bindingHandlers.clickToEdit = {
    init: function(element, valueAccessor) {
        var observable = valueAccessor(),
            link = document.createElement("a"),
            input = document.createElement("input");

        element.appendChild(link);
        element.appendChild(input);

        observable.editing = ko.observable(false);
        ko.applyBindingsToNode(link, {
            text: observable,
            visible: !observable.editing,
            click: function() {
                observable.editing(true);
            }
        });

        ko.applyBindingsToNode(input, {
            value: observable,
            visible: observable.editing,
            hasfocus: observable.editing
        });
    }
};

function ViewModel() {
    this.message = ko.observable("Click on me to edit");
}
ko.applyBindings(new ViewModel());

标签: knockout.js
1条回答
Ridiculous、
2楼-- · 2019-07-16 14:38

Your problem is on this line:

visible: !observable.editing

This will evaluate to false and will stay that way. Even if you do !observable.editing(), then it will be a static true value.

So, there are a couple of ways to handle it:

1 - a good choice is to create a quick hidden binding handler that just passes the opposite value to the visible binding. There are a few ways to write it, but here is a simple way:

ko.bindingHandlers.hidden = {
    update: function(element, valueAccessor) {
        var isVisible = !ko.utils.unwrapObservable(valueAccessor());
        ko.bindingHandlers.visible.update(element, function() { return isVisible; });
    }        
};

Now, you can use:

hidden: observable.editing

Here is a sample: http://jsfiddle.net/rniemeyer/2jg2F/2/

2 - another choice is to add a computed observable that returns the opposite. Something like:

    observable.editing = ko.observable(false);
    observable.notEditing = ko.computed(function() {
       return !observable.editing(); 
    });

Then, binding against notEditing like:

http://jsfiddle.net/rniemeyer/2jg2F/3/

查看更多
登录 后发表回答