-
Notifications
You must be signed in to change notification settings - Fork 8
Custom Two Way bindings
Dmitry Panyushkin edited this page Jul 17, 2018
·
1 revision
If we want to write custom two-way binding that can work with @observable object property,
we can use the following helper.
It wraps @observable object property to hidden writeable ko.pureComputed. And we can work with wrapped property like with regular ko.observable inside the binding.
registerTwoWayBinding("valueWithDefault", {
init(element, valueAccessor, allBindings, viewModel, bindingContext) {
// `value` is always ko.observable
const value = valueAccessor();
value(element.value);
ko.applyBindingsToNode(element, { value }, context);
},
update(element, valueAccessor, allBindings, viewModel, bindingContext) {
// ...
}
});
class ViewModel {
@observable property = "";
}
<input data-bind="valueWithDefault: property" value="Default Value" />
// now viewModel.property === "Default Value"export function registerTwoWayBinding(name, config) {
ko.bindingHandlers[name] = {
init: wrapBindingHandler(name, config.init),
update: wrapBindingHandler(name, config.update)
};
ko.expressionRewriting["_twoWayBindings"][name] = true;
}
function wrapBindingHandler(name, bindingHandler) {
if (!bindingHandler) {
return bindingHandler;
}
return function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var value = valueAccessor();
if (!ko.isObservable(value) && !ko.isWriteableObservable(value)) {
var proxy = ko.pureComputed({
read: valueAccessor,
write: allBindings.get("_ko_property_writers")[name]
});
valueAccessor = function() {
return proxy;
};
}
bindingHandler(element, valueAccessor, allBindings, viewModel, bindingContext);
};
}