1

I have an HTML text input called hours that is verified as a number through a knockout extender. If the user entering the hours has any whitespace after the number they enter, I would like to simply have this trimmed without getting notified that what they've entered for hours is not a number. For example, if they enter "2.5 ", this should be correct as I want the extra spaces trimmed automatically. How am I able to do this with what I have below? Thank you.

hours: ko.observable().extend({ number: true, required: true })
CDA the Programmer
  • 87
  • 1
  • 6
  • 20
  • Why not just make the input of type number --> input type="number". So that spaces will be ignored by default? – Kyle Jan 07 '20 at 22:55
  • @CDA the Programmer, did my answer help you resolve your issue? if so, please mark it as accepted. If not, let me know and I'll try to help further. – OfirD Jan 23 '20 at 22:16

1 Answers1

1

You can add a trimming functionality to observables, e.g. adding a custom function to ko.subscribable.fn as explained in another SO post:

ko.subscribable.fn.trimmed = function() {
    return ko.computed({
       read: function() {
           return this();
       },
       write: function(value) {
           this(value.trim());
           this.valueHasMutated();
       },
       owner: this
   }).extend({ notify: 'always' });
};
var vm = function () {
  this.num = ko.observable().trimmed().extend({ number: true });
  this.num(' 2 ');
}
ko.applyBindings(new vm());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout-validation/2.0.3/knockout.validation.min.js"></script>
<input type="text" data-bind="value: num" />

P.S. Don't be tempted to add a trim() call into Knockout validator plugin number rule:

// this is the original 'number' rule implemetation, with a 'trim()' call added to it
ko.validation.rules['number'] = {
   validator: function (value, validate) {
        if (!validate) { return true; }
        return ko.validation.utils.isEmptyVal(value) || 
               (validate && /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value.trim()));
    },
    message: 'Please enter a number.'
};

... because you don't want the trimming to happen during validation, but much earlier, that is: during the writing.

OfirD
  • 9,442
  • 5
  • 47
  • 90