How to update/filter the underlying observable val

2019-08-16 01:59发布

问题:

Problem

I have created a custom binding that replaces html br occurences in an observable with \r\n in order to be displayed in a textarea. This works OK for the initial display of the value, but furthers changes to the displayed text don't trigger the update function of the custom binding.

Code

ko.bindingHandlers.Br2Nl = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {     
        var observable = valueAccessor();
        var valueUnwrapped = ko.utils.unwrapObservable(observable);
        var transformed = Br2Nl(valueUnwrapped);
        $(element).val(transformed);
    }
};
function Br2Nl(content)
{
    var response = new String(content);
    return response.replace(/<br \/>/g, "\r\n");
}

My initial assumption was that the problem was that I didn't actually trigger the update of the underlying observable so I modified the update function to do so, but with no success:

update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {     
        var observable = valueAccessor();
        var valueUnwrapped = ko.utils.unwrapObservable(observable);
        var transformed = Br2Nl(valueUnwrapped);
        //update observable with transformed value
        observable(transformed);
        $(element).val(transformed);
    }

Is there a proper way to update/filter the value of an observable using a custom binding?

Custom binding usage:

<textarea data-bind="Br2Nl: PropertyName" rows="5">  </textarea>

This is the fiddle for it: http://jsfiddle.net/bWHBU/

As it can be observed, nothing happens to the observable(div below) when the content of the textarea changes. However, when the 'Br2Nl' custom binding is replaced with the 'value' binding, the observable is updated.

Final solution here: http://jsfiddle.net/bWHBU/5/

Replaced 'keyup' with 'change' event to avoid vertical scrollbar repositioning issue on Firefox.

回答1:

You have not instructed knockout when to update the observable property when the text in the text area changes. Try this:

ko.bindingHandlers.Br2Nl = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        ko.utils.registerEventHandler(element, "keyup", function() {
            var observable = valueAccessor();
            var valueUnwrapped = ko.utils.unwrapObservable(observable);    
            var transformed = Br2Nl($(element).val());
            observable(transformed);
        });
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {     
        var observable = valueAccessor();
        var valueUnwrapped = ko.utils.unwrapObservable(observable);
        var transformed = Br2Nl(valueUnwrapped);
        $(element).val(transformed);
    }
};

It might take a bit of tinkering to get the keyup method correct, but that should be a good start.

Updated your jsFiddle. You were referencing raw.github for the mapping plugin, and browsers can't parse files from there correctly. Added a usable external reference.