Reputation: 4167
I'm currently building a number heavy app in Knockout. In my app there are three types of numbers: percentages, decimals and large numbers and I have custom binding handlers for each type.
For the inputs I've also created a number validation bindingHandler that reads each keypress to ensure that it's a number being input. (in the app there's flashy border CSS animations and stuff - this is just a bare bones stripped down example).
Now to have the inputs carry out the validation checks and the number formatting, I've had to bind the variable twice as you'll see properly in the fiddle below.
<input data-bind="number: testdata, percentage: testdata">
I'm thinking that this is unnecessarily bloating my HTML markup and there has to be a tidier way to trigger both handlers at the same time.
My question: Is it possible to create the number validation script as a function which can then be shared/included inside of the number formatting handlers; without bloating my Javascript?
I'm still relatively a newbie at Knockout so I'm still unsure of it's boundaries.
See Fiddle: http://jsfiddle.net/axV6S/1/
Upvotes: 5
Views: 105
Reputation: 6909
You are duplicating a lot of built in functionality within knockout. When creating your viewmodel you can define restrictions for your model properties. You can do this for a lot of your numerical data:
this.FieldName = ko.observable().extend({ pattern: regex });
This will constrain your text fields,a nd you do not need to listen for keypresses, and take action. Knockout does this in the background for you!
Have a look at this for more examples: http://mikedormitorio.azurewebsites.net/BlogPost/the-native-validation-rules-of-knockout-validation
This is also a helpful read: http://knockoutjs.com/documentation/extenders.html
Upvotes: 0
Reputation: 51810
Yes, you can just extract out the number init into its own function, i.e. change this:
ko.bindingHandlers.number = {
init: function (element) {
/* ... */
}
};
into this:
var numberInit = function(element) {
/* ... */
};
Just call it from your other init like this:
init: function(element, valueAccessor) {
numberInit(element);
/* ... */
}
or if you want to keep the right 'this' context:
init: function(element, valueAccessor) {
numberInit.apply(this,arguments);
/* ... */
}
Upvotes: 2