Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knockoutjs submit binding not handling enter key properly

I have a jquery ui dialog with a knockoutjs submit binding on a form. The dialog can be closed either by pressing the cancel button, by pressing the close button on the dialog title bar, by hitting escape, or by pressing the save button. My intent is that the cancel, escape, and title bar close events should dismiss the dialog without applying any actions from it, whereas pressing enter or clicking 'save' should perform the dialog action. Everything works as intended, except the enter key, which results in a cancel event, rather than in a submit event.

I've created a jsfiddle to illustrate this, and include code below for referernce.

My apologies for the verbose code...

Gene

<!-- ko with: dialog -->
<div id="taskdlg" class="resizeableDialog" 
    data-bind="dialog: {autoOpen: false, title: 'Edit task', height: 200, width: 500, modal: true, close: updateCloseState}, openWhen: open">
    <form data-bind="submit: update">
        <table>
            <tr>
                <td style="width: 100px;"><label for="tasktitle">Title</label></td>
                <td width="*">
                    <input id="tasktitle" type="text" placeholder="Task name" data-bind="value: titletext, valueUpdate: 'afterkeydown'" />
                </td>
            </tr>
            <tr>
                <td><button style="float: left;" data-bind="click: cancel">Cancel</button></td>
                <td><button style="float: right;" type="submit">Save</button></td>
            </tr>
        </table>
    </form>
</div>
<!-- /ko -->

<button data-bind="click: editTask">Edit</button>
<span data-bind="text: task"></span>

The javascript is as follows:

ko.bindingHandlers.dialog = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        var options = ko.utils.unwrapObservable(valueAccessor());
        setTimeout(function() { $(element).dialog(options || {}); }, 0);

        //handle disposal (not strictly necessary in this scenario)
         ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
             $(element).dialog("destroy");
         });   
    },
    update: function(element, valueAccessor, allBindingsAccessor) {
         var shouldBeOpen = ko.utils.unwrapObservable(allBindingsAccessor().openWhen);
         $(element)
             .dialog(shouldBeOpen ? "open" : "close");
    }
};

function Task(name) {
    var self = this;
    this.title = ko.observable(name);

    this.toString = function() { return "Task: " + self.title(); };
}

function TaskDialog(viewModel) {
    var self = this;

    this.viewModel = viewModel;
    this.task = ko.observable();
    this.open = ko.observable(false);
    this.titletext = ko.observable();

    this.editTask = function(task) {
        self.task(task);
        self.titletext(task.title());
        self.open(true);
    }

    this.update = function() {
        var task = self.task();
        task.title(self.titletext());
        self.open(false);
    }

    this.updateCloseState = function() {
        if (self.open())
            self.open(false);
    }

    this.cancel = function() {
        self.open(false);
    }
}


function viewModel() {
    var self = this;
    this.dialog = ko.observable(new TaskDialog(self));
    this.task = ko.observable(new Task('sample task'));

    this.editTask = function() {
        self.dialog().editTask(self.task());
    }
};

ko.applyBindings(new viewModel());
like image 311
Gene Golovchinsky Avatar asked Dec 28 '11 07:12

Gene Golovchinsky


1 Answers

If a button does not have a type, then the browser makes an assumption that it can be considered a submit button. So, when you hit enter the cancel button's method is being executed and preventing the default submit from actually happening. So, if you were to move the Save button before the Cancel button it would work properly.

However, the real way to fix it is just to add type="button" to your Cancel:

<button type="button" style="float: left;" data-bind="click: cancel">Cancel</button>

http://jsfiddle.net/rniemeyer/HwbD2/11/

like image 193
RP Niemeyer Avatar answered Nov 06 '22 06:11

RP Niemeyer