Call a function on enter key press

knockout.js

knockout.js Problem Overview


How to call a function using knockout.js when enter key is pressed.. here is my code below.

ko.bindingHandlers.enterkey = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
    var inputSelector = 'input,textarea,select';
    $(document).on('keypress', inputSelector, function (e) {
        var allBindings = allBindingsAccessor();
        $(element).on('keypress', 'input, textarea, select', function (e) {
            var keyCode = e.which || e.keyCode;
            if (keyCode !== 13) {
                alert('a');
                return true;
            }

            var target = e.target;
            target.blur();

            allBindings.enterkey.call(viewModel, viewModel, target, element);
            alert('b');
            return false;
        });
    });
}
};
ko.applyBindings(viewModel);

HTML

<input type="text" data-bind="value:sendMessageText, enterkey: sendMessage" /> 

ViewModel

function contactsModel(){
    var self = this;
    self.jid=ko.observable();
    self.userName=ko.observable();
    self.sendMsgText=ko.observable();
    self.sendMessage = function(){
        if(self.sendMessageText() == '' )
            alert("Enter something in input field");
        else{
            var message = {
                to : self.userName(),
                message : self.sendMsgText()
            }
            self.sentMessages.push(message);
            sendMessage(message);
        }

     }
 }

Any idea's about what is wrong here or suggestions for better approach.

knockout.js Solutions


Solution 1 - knockout.js

No need for a custom binding, just use knockout's keypress event(Knockout docs):

<input type="text"
       data-bind="textInput : keyword, 
                  event: {keypress: onEnter}" >
</input>

And your function:

that.onEnter = function(d,e){
    e.keyCode === 13 && that.search();  
    return true;
};

JSFiddle example

EDIT: New binding from knockout(3.2.0) : textInput - obviates the need to have a valueUpdate binding.

Solution 2 - knockout.js

When you create your own knockout bindingHandler, it is used in the same way as the other bindingHanlders eg: data-bind="text: myvalue"

so your HTML will need to look something like this

<input type="text" data-bind="value:sendMessageText, valueUpdate: 'afterkeydown', enterkey: sendMessage" />

An important binding to add is the valueUpdate: 'afterkeydown' binding. Without this binding when a user types text in the input and hits enter the onblur event is not raised prior to enterkey binding. This results in the observable returning an unexpected value and not the current text if the input's value is accessed in an action invoked by enterKey.

Another Look at Custom Bindings for KnockoutJS

EDIT
This is what I have used previously on other projects. JsFiddle Demo

ko.bindingHandlers.enterkey = {
    init: function (element, valueAccessor, allBindings, viewModel) {
        var callback = valueAccessor();
        $(element).keypress(function (event) {
            var keyCode = (event.which ? event.which : event.keyCode);
            if (keyCode === 13) {
                callback.call(viewModel);
                return false;
            }
            return true;
        });
    }
};

Solution 3 - knockout.js

This worked for me, thanks to @DaafVader for most of it.

in view

<input data-bind="value: searchText, valueUpdate: 'input', event: { keyup: searchKeyUp }" />

in viewmodel

var searchKeyUp = function (d, e) {
    if (e.keyCode == 13) {
        search();
    }
}

Solution 4 - knockout.js

And this worked for me, thanks to @DaafVader.

in view:

<input id="myInput" type="text" 
      data-bind="value : keyword, valueUpdate: 'afterkeydown'">
</input>

in javascript:

$("#myInput").keyup(function (event) {
        if (event.keyCode == 13) {
            search();
        }
});

To put keyup event in your jquery event instead of knockout event reduced the complexity of the knockout viewmodel.

Solution 5 - knockout.js

Use the submit binding (http://knockoutjs.com/documentation/submit-binding.html) on the form around your input, that's what it's made for.

Example from the Knockout docs:

<form data-bind="submit: doSomething">
    ... form contents like inputs go here ...
    <button type="submit">Submit</button>
</form>
 
<script type="text/javascript">
    var viewModel = {
        doSomething : function(formElement) {
            // ... now do something
        }
    };
</script>

It also automatically handles your button if there is one.

Categories
Recommended knockout.js Solutions

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDaveView Question on Stackoverflow
Solution 1 - knockout.jsDaafVaderView Answer on Stackoverflow
Solution 2 - knockout.jsNathan FisherView Answer on Stackoverflow
Solution 3 - knockout.jsjacobsgriffithView Answer on Stackoverflow
Solution 4 - knockout.jsLuo Jiong HuiView Answer on Stackoverflow
Solution 5 - knockout.jsMafiiView Answer on Stackoverflow