I'm trying to create a number input box which will accept numbers only.
My initial value approach was to replace value and set it again to itself.
Subscribe approach
function vm(){
var self = this;
self.num = ko.observable();
self.num.subscribe(function(newValue){
var numReg = /^[0-9]$/;
var nonNumChar = /[^0-9]/g;
if(!numReg.test(newValue)){
self.num(newValue.toString().replace(nonNumChar, ''));
}
})
}
ko.applyBindings(new vm())
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input type="text" data-bind="textInput: num" />
Now this approach works but will add another cycle of subscribe event, so I tried to use a custom binding so that I can return updated value only. New to it, I tried something but not sure how to do it. Following is my attempt but its not working. Its not even updating the observable.
Custom Binding attempt
ko.bindingHandlers.numeric_value = {
update: function(element, valueAccessor, allBindingsAccessor) {
console.log(element, valueAccessor, allBindingsAccessor())
ko.bindingHandlers.value.update(element, function() {
var value = ko.utils.unwrapObservable(valueAccessor());
return value.replace(/[^0-9]/g, '')
});
},
};
function vm() {
this.num = ko.observable(0);
this.num.subscribe(function(n) {
console.log(n);
})
}
ko.applyBindings(new vm())
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div>
<input type="text" data-bind="number_value: num, valueUpdate:'keyup'">
<span data-bind="text: num"></span>
</div>
So my question is, Can we do this using custom bindings and is it better approach than subscribe one?
Edit 1:
As per @user3297291's answer, ko.extenders looks more like a generic way for my subscribe approach. I'm looking for an approach (if possible in Knockout), which would clean value before it is set to observable.
I have taken reference from following articles:
- How to update/filter the underlying observable value using a custom binding?
- How can i update a observable in custom bindings?
Note: In the first example, they are using jQuery to set the value. I would like to avoid it and do it using knockout only
textInputbut little tied up stuff. Will add answer later. Also, in your fiddle, characters are visible for fraction of second and for some cases(if 1 character is entered), character is retained. - Rajesh