ShaneKm
ShaneKm

Reputation: 21308

knockout get old value of the text box

I'm using mapping plugin. I have an on 'blur' event whenever someone takes away focus from a text box. I would like to know if the old value is different from new value. This works correct for "enter" key. For some reason whenever I change the value and press enter I get this console output FIRST time; 'oldValue | newValue'. However this is not the case when 'blur' fires. I get 'newValue | newValue'

How come?. How can i get the new and old values on blur?

HTML:

<input class="percent-text" data-bind="text: Percent, value: Percent, event: { keypress: $root.percentUpdate, blur: $root.percentUpdate }" type="number" min="1" max="100" oninput="maxlength(this)" maxlength="3" />

Knockout:

    self.percentUpdate = function (data, event) {
        if (event.keyCode === 13 || event.type == 'blur') {
            var $target = $(event.currentTarget);
            console.log(data.Percent() + " | " + event.target.value); 
        }
        return true;
    };

Upvotes: 0

Views: 2052

Answers (2)

webketje
webketje

Reputation: 10966

You could do it with your approach (I had a succesful testcase), but as @AnotherDev mentioned it's simpler to use the built-in tools. Inside the subscribe function you have access to the value before or after it is changed, and act upon it accordingly. If you want to still be able to retrieve previous values afterwards, you could easily do this with caching the preceding value, or even all preceding values (in an array). Note that the only reason cachedPercent(s) are observable in the fiddle is to update the viewModel JSON; in a real app I would use plain array/ number (and ev. in private variable).

Test it in the fiddle below; wth this approach the ENTER key function only needs a manual call to valueHasMutated to notify the subscribe function.

function App(percent) {
  var self = this;
  this.cachedPercent = ko.observable(percent || 0);
  this.cachedPercents = ko.observableArray([percent || 0]);
  this.PercentRaw = ko.observable(percent || 0);
  // Percent stores an integer, and is ratelimited to make sure
  // that the value isn't stored 1000x every time the user increments
  this.Percent = ko.computed(function() { 
    return parseInt(self.PercentRaw()); 
  }).extend({rateLimit: 500});
  this.storePercents = this.Percent.subscribe(function(oldVal) {
    // delete this if clause if you want to manually check somewhere else
    // because this tells JS not to store any value when similar to the previous one
    if (self.cachedPercent() !== oldVal) {
      self.cachedPercent(self.Percent());
      self.cachedPercents.splice(0, 0, self.Percent());
    }
  }, null, 'beforeChange');
}
ko.applyBindings(new App(50));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<input data-bind="value: PercentRaw, 
                  event: {keydown: function(d, e) { if (e.keyCode === 13) PercentRaw.valueHasMutated(); } " type="number" min="1" max="100" maxlength="3" class="percent-text" />

<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>

Upvotes: 1

tcigrand
tcigrand

Reputation: 2397

Knockout updates the value on blur and the value is probably getting updated before your blur event. I don't know exactly what you're trying to do, but I would look into using .subscribe and .subscribe with beforeChange.

http://knockoutjs.com/documentation/observables.html

For example

data.Percent.subscribe(function(newValue) {
    alert(newValue)
});

And

data.Percent.subscribe(function(oldValue) {
        alert(oldValue)
    }, null, "beforeChange");

Upvotes: 1

Related Questions