AndrewC
AndrewC

Reputation: 351

Update observable bound to input value only on enter key press

I've got a text field that is bound to an observable:

<input type="text" data-bind="value: chartOptions.zoomLevel" value="100%" />

This works fine, except that the field needs to lose focus before the observable is updated. What I need is to update that the observable only changes when the enter key is pressed.

I've looked at the possible valueUpdate parameters, but none of them seem to be suitable.

Upvotes: 2

Views: 2158

Answers (2)

Dunc
Dunc

Reputation: 18922

Here's a polyfill that may help - forces IE to fire 'change' event on enter key (as other browsers do) which in turn triggers Knockout's value binding.

var isIE = !!document.documentMode;
if (isIE) {

    $("body").on("keydown", "input[type='text']", function (e) {

        // Ensure 'value' binding is fired on enter in IE
        if ((e.keyCode || e.which) === 13) {
            $(this).blur();
        }
    });
}

Upvotes: 0

Jeroen
Jeroen

Reputation: 63699

There's probably a way to do this with custom bindings, but here's a straightforward way to do it using the event binding. You seem to imply that the observable should only change iif the enter key is pressed. However, I've added the blur event as a trigger too; it's easy to remove that anyhow.

var ViewModel = function() {
  var self = this;
  
  self.zoomLevel = ko.observable('100');
  self.newZoomLevel = ko.observable('100');
  
  self.tryCommitZoomLevel = function(data, event) {
    if (event.keyCode === 13 || event.type === "blur") {
      self.zoomLevel(event.target.value);
    }
    
    // Make sure the event bubbles to let the value binding also handle events:
    return true;
  };
};

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input type="text" data-bind="event: { keypress: tryCommitZoomLevel, blur: tryCommitZoomLevel }, value: newZoomLevel" />
<br />
The zoom level you've entered is: <strong data-bind="text: zoomLevel"></strong>%

The snippet keeps a seperate "new value" copy of the actual observable, and only commits it if the user presses enter or the input looses focus.

Upvotes: 1

Related Questions