Create 2 way custom binding with observable plugin

断了今生、忘了曾经 提交于 2019-12-05 04:59:46

问题


The clues for this question seem so hard to find that I begin to think it must be either obvious (and I'm missing something), useless, or impossible:

I get the 2-way binding thing in knockout with observables (ko.observables()). However all this parenthesis are a real pain. So as I'm using Durandal, I though I'd give the observableplugin a try : http://durandaljs.com/documentation/Binding-Plain-Javascript-Objects.html

(for the record, I also tried this one: http://blog.stevensanderson.com/2013/05/20/knockout-es5-a-plugin-to-simplify-your-syntax/)

Both are working fine with knockout's valuebinding.

My problem is I have multiple knockout custom bindings for my application and I don't get how you update an observable property that is not a ko.observable() in these custom bindings.

In my binding I would normally do this:

ko.bindingHandlers.testBinding = {
    init: function(element, valueAccessor) {
        var myObservable = valueAccessor();
        // here I could detect if it's an observable or a POJO
        // ... how to know if it's a property ???

        $(element).blur(function() {

            // ... how to write to myObservable if it's a writable property
            // ... and not a ko.observable() ???
            myObservable($(element).val());

        });

    },
    update: function(element, valueAccessor) {
        $(element).val(ko.unwrap(valueAccessor()));
    }
};

However with observables, I understand I'd need the reference to the underlying object and the name of the property to perform an update. (I can get the former but how to get the latter?)

I've looked into the value binding of knockout to try to understand but without more success...

Would someone have a simple example of how it would look like with the observable plugin? Any clue would be much appreciated.

Thanks


回答1:


Using Knockout's preprocess feature, your binding can add a method to write to the property directly. Here's how you could do it:

ko.bindingHandlers.testBinding = {
    preprocess: function(value, name, addBindingCallback) {
        addBindingCallback('testBindingWriter', 'function(v){' + value + ' = v}');
        return value;
    },
    init: function(element, valueAccessor, allBindings) {
        var value = valueAccessor();
        $(element).blur(function() {
            if (ko.isObservable(value)) {
                value($(element).val());
            } else {
                allBindings.get('testBindingWriter')($(element).val());
            }
        });
    },
    update: function(element, valueAccessor) {
        $(element).val(ko.unwrap(valueAccessor()));
    }
};

Example: http://jsfiddle.net/mbest/U7Jeg/




回答2:


If all you want to do is get the property name you can use preprocess to store it on the binding handler like this:

propertyName: null,
preprocess: (value) => {
        this.propertyName = value;
        return value;
},

You can now access the property in your init function and combine it with bindingContext to set the value:

init: (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) => {
        $(element).blur(() => {
            bindingContext.$data[this.propertyName] = $(element).val();
        })
}

Note: I'm using an arrow function above to preserve the meaning of "this." If that isn't an option for, you can do this instead:

init: (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) => {
        thisHandler = this;
        $(element).blur(function () {
            bindingContext.$data[thisHandler.propertyName] = $(element).val();
        })
}


来源:https://stackoverflow.com/questions/22789732/create-2-way-custom-binding-with-observable-plugin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!