0

I have not used Knockout in a while and am running into an issue when trying to trim the input value of a form field to two decimal places. I created the below computed observable and am subscribing to it by the observable that I want to update with the trimmed value. Can anyone tell me what I am doing wrong?

View Model

function createViewModel() {
  var self = {};

  self.SalesRepId = ko.observable().extend({ required: true });
  self.PriceAdvanced = ko.observable("").extend({ required: true, min: 1, max: 200 });

  self.decimalValue = ko.computed(function () {
    var num = self.PriceAdvanced().slice(0, (self.PriceAdvanced().indexOf(".")) + 3);
    return num;
  }).extend({ notify: "always" });

  self.PriceAdvanced.subscribe(self.decimalValue);

  return self;
}

HTML:

<div class="form-group col-xs-12">
          <label class="label-col col-xs-4 control-label labelFormat" for="PriceAdvanced"><span class="warn">* </span>Advanced Criminal History Search</label>
          <div class="col-xs-8">
            <input class="form-control max225" type="text" id="PriceAdvanced" name="PriceAdvanced" data-bind="textInput: PriceAdvanced" size="23" placeholder="$0.00" />
          </div>
</div>
Ray
  • 3,864
  • 7
  • 24
  • 36
Dean Friedland
  • 773
  • 2
  • 12
  • 32

1 Answers1

1
  1. Were you calling the ko.applyBindings method? If not, you need to call that at the end of your code.
  2. I think your idea was to use decimalValue to limit the decimal places to 2, and then PriceAdvanced would subscribe to the updated value of decimalValue, right? But subscribe doesn't work like that. Computed observables listen to the observables inside them, and .subscribe functions are listeners to the observable itself. So your code would have been in a never-ending loop.
  3. Also I think you only wanted to limit decimal places, not the number of digits itself right? So I changed the code to trim the value only if a decimal point exists.

    function createViewModel() {
      var self = {};
    
      self.SalesRepId = ko.observable().extend({ required: true });
      self.PriceAdvanced = ko.observable("").extend({ required: true, min: 1, max: 200 });
    
      self.decimalValue = ko.computed(function () {
          var num = self.PriceAdvanced().indexOf(".") > -1?  self.PriceAdvanced().slice(0, (self.PriceAdvanced().indexOf(".")+3)): self.PriceAdvanced();
          //return num;
          self.PriceAdvanced(num);
      }).extend({ notify: "always" });
      return self;
    }
    
    ko.applyBindings(new createViewModel());
    

Note: Your extenders min: 1, max: 200 will not work as PriceAdvanced holds a string rather than a number.

Ray
  • 3,864
  • 7
  • 24
  • 36
  • Thank you Ray. This worked perfectly! However, I still have the issue with the min/max validation. Any idea on how to make that work in this case? – Dean Friedland Apr 06 '18 at 03:13
  • @DeanFriedland I'm not sure if min and max are valid extenders, because according to [this question](https://stackoverflow.com/questions/42922022/max-value-and-numerical-validation-in-knockoutjs), you need the plugin for it to work. Without that, you might need to write a custom extender like in the documenation http://knockoutjs.com/documentation/extenders.html – Ray Apr 06 '18 at 03:20
  • The custom extender should ideally include the decimal limiter as well. – Ray Apr 06 '18 at 03:22
  • Yes, we have the validation plugin/library and it is in there. Just not sure why it is not firing – Dean Friedland Apr 06 '18 at 03:22
  • You could also try applying numbers to PriceAdvanced instead of a string, and use [this logic](https://stackoverflow.com/questions/6525335/trim-to-2-decimals) to limit the decimal places. – Ray Apr 06 '18 at 03:24
  • @DeanFriedland oh I see... You could ask a new question, to see why it is not firing, because you would probably need to rewrite the logic if you want to use that plugin as well. – Ray Apr 06 '18 at 03:26
  • How would I apply numbers as opposed to a string for that observable? Sorry if that is a dumb question. – Dean Friedland Apr 06 '18 at 03:27
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/168363/discussion-between-ray-and-dean-friedland). – Ray Apr 06 '18 at 03:28