Insights and discoveries
from deep in the weeds
Outsharked

Wednesday, May 15, 2013

Adding "enter key" handling to forms using Knockout.js & jQuery

Been a long time since my last post here, busy year! And man does this blog layout look dated.. priorities...

Here's a quick and easy solution to a problem for which I didn't find a complete solution elsewhere. A nice input form UI will let the user press the ENTER key to submit the form. Browsers don't have a predictable and consistent handling of this action, especially if there's more than one form on a page. Furthermore, if you aren't actually using a submit type element, browsers won't do anything as they have no way of knowing the intent anyway.

This extender for knockout.js + jQuery adds this functionality. All you need to do is add a binding for enterkey to an element that wraps your form, and pressing enter on any input control that's a descendent of the element containing the binding will cause that controller method to be invoked.

Example knockout bindings:
    <div id="form1" data-bind="enterkey: submit">
       Name: <input type=text data-bind="value: fullname">
       ... more fields ...

       <a href="#" data-bind="click: submit">Save</a>
    </div>

    <script type="text/javascript">
        var model = {
            fullname: ko.observable(),
            // ... more fields
            submit: function() {
                // process the form
            }
        };
        ko.applyBindings(model);
    </script>
The code:
ko.bindingHandlers.enterkey = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
       var allBindings = allBindingsAccessor();

            $(element).on('keypress', 'input, textarea, select', function (e) {
                var keyCode = e.which || e.keyCode;
                if (keyCode !== 13) {
                    return true;
                }

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

                allBindings.enterkey.call(viewModel, viewModel, target, element);

                return false;
            });
        }
    }
};
See an example on JsFiddle