Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

make an input only-numeric type on knockout

Tags:

i read many tutorials but i dont know how to do this, this is the input

input(type="text",name="price",id="price"data-bind="text: price,valueUpdate:['afterkeydown','propertychange','input']")

and this is my viewModel

price: ko.computed(function()
{
    return parseFloat(this.replace(' ','').replace(/[^0-9\.]+/g,"")) || '';
},this)

but this cause error: this has no method replace??? how can i pass the price value to the computed function??

like image 760
andrescabana86 Avatar asked Jun 11 '13 15:06

andrescabana86


People also ask

How do I force input fields into numbers only?

By default, HTML 5 input field has attribute type=”number” that is used to get input in numeric format. Now forcing input field type=”text” to accept numeric values only by using Javascript or jQuery. You can also set type=”tel” attribute in the input field that will popup numeric keyboard on mobile devices.

What is KnockoutJS used for?

KnockoutJS is basically a library written in JavaScript, based on MVVM pattern that helps developers build rich and responsive websites.

How do you activate a KnockoutJS model?

To activate Knockout, add the following line to a <script> block: ko. applyBindings(myViewModel); You can either put the script block at the bottom of your HTML document, or you can put it at the top and wrap the contents in a DOM-ready handler such as jQuery's $ function.


2 Answers

Is better to create custom binding http://knockoutjs.com/documentation/custom-bindings.html which accept only allowed characters [0-9,.] as numeric representation.

put this line into your view

<input id="text" type="text" data-bind="numeric, value: number">

put this line into your model (remember to bind number as observable property)

ko.bindingHandlers.numeric = {
    init: function (element, valueAccessor) {
        $(element).on("keydown", function (event) {
            // Allow: backspace, delete, tab, escape, and enter
            if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||
                // Allow: Ctrl+A
                (event.keyCode == 65 && event.ctrlKey === true) ||
                // Allow: . ,
                (event.keyCode == 188 || event.keyCode == 190 || event.keyCode == 110) ||
                // Allow: home, end, left, right
                (event.keyCode >= 35 && event.keyCode <= 39)) {
                // let it happen, don't do anything
                return;
            }
            else {
                // Ensure that it is a number and stop the keypress
                if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105)) {
                    event.preventDefault();
                }
            }
        });
    }
};
like image 128
Martin Surynek Avatar answered Oct 12 '22 14:10

Martin Surynek


Knockout has extenders for this. Check This from knockoutjs.com explaining how to use observable extenders to force input to be numeric. I paste the code from the documentation here:

Source code: View

<p><input data-bind="value: myNumberOne" /> (round to whole number)</p>
<p><input data-bind="value: myNumberTwo" /> (round to two decimals)</p>

Source code: View model

ko.extenders.numeric = function(target, precision) {
    //create a writable computed observable to intercept writes to our observable
    var result = ko.pureComputed({
        read: target,  //always return the original observables value
        write: function(newValue) {
            var current = target(),
                roundingMultiplier = Math.pow(10, precision),
                newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue),
                valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;

            //only write if it changed
            if (valueToWrite !== current) {
                target(valueToWrite);
            } else {
                //if the rounded value is the same, but a different value was written, force a notification for the current field
                if (newValue !== current) {
                    target.notifySubscribers(valueToWrite);
                }
            }
        }
    }).extend({ notify: 'always' });

    //initialize with current value to make sure it is rounded appropriately
    result(target());

    //return the new computed observable
    return result;
};

function AppViewModel(one, two) {
    this.myNumberOne = ko.observable(one).extend({ numeric: 0 });
    this.myNumberTwo = ko.observable(two).extend({ numeric: 2 });
}

ko.applyBindings(new AppViewModel(221.2234, 123.4525));
like image 27
Lemo Avatar answered Oct 12 '22 15:10

Lemo