mat-mcloughlin
mat-mcloughlin

Reputation: 6702

Binding keypress event on knockoutjs, observable not populated

Need a little help with knockoutjs and binding a keypress event. I'm trying to hook up knockout so that I pick up on the enter keypress from within a text box. So I can perform the same action as clicking a button. Its a little tricky to explain but hopefully this JsFiddle will demonstrate what I'm trying to achieve.

http://jsfiddle.net/nbnML/8/

The problem I have is that observable value is not getting updated and I think its something to do with an observable not being updated until focus moves away from the textbox?

Any solutions to this problem.

Thanks!

Upvotes: 12

Views: 17201

Answers (2)

jnewcomb
jnewcomb

Reputation: 21

Don't discount submit bindings: http://knockoutjs.com/documentation/submit-binding.html

This takes care of some IE 9/10 gotchas such as the return key not updating the observable. With this taken care of you don't need to intercept keycode 13

html:

<form data-bind="submit:RunSomething">
 <input type="text" data-bind="value: InputValue" />
 <input type="submit" value="test" />
 <div data-bind="text: InputValue" />
</form>

code:

var ViewModel = function () {
    var self = this;
    self.InputValue = ko.observable('');

    self.RunSomething = function (ev) {
        window.alert(self.InputValue());
    }
}
ko.applyBindings(new ViewModel());

See this here:

http://jsfiddle.net/jnewcomb/uw2WX/

Upvotes: 1

RP Niemeyer
RP Niemeyer

Reputation: 114792

One option is to use the valueUpdate additional binding to force an update on each keypress. For example, you would do:

<input type="text" data-bind="value: InputValue, valueUpdate: 'afterkeydown', event: { keypress: RunSomethingKey }" />

If that is not what you are after, then really you would want to fire the element's change event in your handler. For example with jQuery, you would do something like: $(event.target).change();.

It would be better though to move this into a custom binding. Maybe something like (probably should check if the result of valueAccessor() is a function):

ko.bindingHandlers.enterKey = {
    init: function(element, valueAccessor, allBindings, vm) {
        ko.utils.registerEventHandler(element, "keyup", function(event) {
            if (event.keyCode === 13) {
                ko.utils.triggerEvent(element, "change");
                valueAccessor().call(vm, vm); //set "this" to the data and also pass it as first arg, in case function has "this" bound
            }

            return true;
        });
    }         
};

Here is your sample updated: http://jsfiddle.net/rniemeyer/nbnML/9/

Upvotes: 38

Related Questions