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());
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/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With