2011-12-28 88 views
7

我有一个jQuery UI对话框与表单上的knockoutjs提交绑定。对话框可以通过按下取消按钮,按对话框标题栏上的关闭按钮,按下转义键或按保存按钮来关闭。我的意图是取消,转义和标题栏关闭事件应该关闭对话框而不应用任何动作,而按下回车或点击'保存'应该执行对话动作。一切都按预期工作,除了输入键,这会导致取消事件,而不是提交事件。knockoutjs提交绑定不处理输入密钥正确

我已经创建了一个jsfiddle来说明这一点,并且包含以下用于引用的代码。

我道歉了冗长的代码...

基因

<!-- 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> 

的JavaScript如下:

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()); 

回答

15

如果一个按钮没有一个类型,然后在浏览器假定它可以被认为是一个submit按钮。因此,当您点击enter时,取消按钮的方法正在执行并阻止实际发生的默认提交。所以,如果您在取消按钮之前移动保存按钮,它将正常工作。

然而,要解决它的真正的方法就是增加type="button"到您的取消:

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

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

+2

谢谢!这是惊人的,愚蠢的小东西浪费了多少时间...... – 2011-12-28 18:13:21

+2

是的,我花了很长时间在看这个。只是似乎有些东西我们错过了,它并不需要大量的代码来捕获keyCode 13,等等...... – 2011-12-28 18:15:25