knockoutjs 提交绑定未正确处理输入键

发布于 2024-12-23 06:26:31 字数 3259 浏览 0 评论 0原文

我有一个 jquery ui 对话框,在表单上有一个 knockoutjs 提交绑定。可以通过按取消按钮、按对话框标题栏上的关闭按钮、按转义键或按保存按钮来关闭对话框。我的意图是取消、转义和标题栏关闭事件应该关闭对话框而不应用任何操作,而按 Enter 或单击“保存”应该执行对话框操作。一切都按预期工作,除了 Enter 键之外,它会导致取消事件,而不是提交事件。

我创建了一个 jsfiddle 来说明这一点,并包含下面的代码以供参考。

我对冗长的代码表示歉意......

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>

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

伴我老 2024-12-30 06:26:31

如果按钮没有类型,则浏览器会假设它可以被视为提交按钮。因此,当您按下 enter 时,取消按钮的方法就会被执行,并阻止默认提交的实际发生。因此,如果您将“保存”按钮移到“取消”按钮之前,它将正常工作。

但是,解决此问题的真正方法是将 type="button" 添加到“取消”:

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

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

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/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文