【问题标题】:Two submit buttons in one form. Can event in submit function know which one?一个表单中有两个提交按钮。提交函数中的事件可以知道是哪一个吗?
【发布时间】:2014-10-02 14:20:03
【问题描述】:

我想知道在 JQuery 中是否有可能:

<form id="testform">
    <input type="text" id="hi" name="hi" />
    <input type="text" id="bye" name="bye" />

    <button type="submit" id="submit1">Use Me</button>
    <button type="submit" id="submit2">No, Use Me </button>
</form>


$('#testform').submit(function(e) {

    e.preventDefault();

    var submiturl;

    if (e.name === 'submit1') { submiturl = '../sendToFactory.cshtml'; }
    else if (e.name === 'submit2') { submiturl = '../sendOverseas.cshtml'; }

    $.ajax({
        url: submiturl,
        data: $('testform').serialize(),
        type: 'POST',
        datatype: 'json',
        success: function (response) {
            //stuff
        },
        error: function (response) {
            //error
        }
    });
});

我知道e.name 不对,但一定有办法做类似的事情,不是吗?

而且我使用的是 IE9 及以上版本。

【问题讨论】:

  • 你应该在提交按钮上绑定click事件而不是表单submit事件
  • @ApulGupta - 好的,但是为什么呢?显然,我对提交函数和事件参数的工作方式存在误解。因此,解释为什么我需要使用单击而不是提交来执行此操作比指令要好得多。如果你不想为此烦恼,那很好。但我只是把它放在那里给一般的回答者。

标签: javascript jquery forms form-submit jquery-events


【解决方案1】:

您可以将“type='submit'”转为“type='button'”,这样它就不会提交表单并监听按钮的点击:

$("#testform button[type=button]").click(function (e) {
    var submitUrl;
    switch ($(e.target).attr('id')) {
        case 'submit1':
            submitUrl = 'url1.cshtml';
            break;
        case 'submit2':
            submitUrl = 'url2.cshtml';
            break;
    }

    $.ajax({
                //...
    })
});

【讨论】:

  • 当你可以做e.target.id时,你为什么要做$(e.target).attr('id')?你为什么打电话给jQuery 只是为了得到身份证?事件处理程序应该做它的事情并离开。调用jQuery 会慢很多。 (为了安全起见,使用我的例子,你应该使用(e.target||{id:''}).id)它仍然会优于jQuery
  • @IsmaelMiguel,你是对的,但就我自己而言,我并不关心 0.001% 的性能提升。此外,jQuery 负责跨浏览器的兼容性。只要每个浏览器都支持“e.target.id”语法,您的解决方案就可以工作。但是如果,一些,比如 1337 版本的 IE,由于某种原因改变了它,它不会。
  • 嗯,IE 是一种癌症,但如果e.target.id 中断,那么 ALL 对象将不起作用。例如:document.getElementsByTagName('body')[0].style.backgroundColor 也会中断。这将使大多数现有的库和网站变得无用。
  • 你是对的。这只是我个人的风格。在大多数情况下,我在单击事件侦听器中执行了更复杂的逻辑,而不仅仅是获取 .id,这就是为什么我的反应是“我首先要来自目标的 jQuery”。
【解决方案2】:

您可以在处理submit 事件时从new FormData(form) 中提取信息,其中form 是对&lt;form&gt; 元素的引用。请注意,您必须在处理事件时提取信息,因为即使您经过事件循环(例如setTimeout(..., 0)),提交按钮信息也已经丢失。

It turns out that latest browsers do not populate FormData with the submit button anymore. 所以现在你可以做如下的事情,参考&lt;form&gt; 元素为form

form.addEventListener('submit', function(event)
{
    event.preventDefault();
    var formdata = new FormData(form);
    formdata.append(event.submitter.name, event.submitter.value);
    ...
    xhr.send(formdata);
}

event.submitter 将包含对提交表单的表单按钮的引用。

如果表单可能有多个 submit 事件处理程序,并且其中一个或多个可能在提交之前实际修改表单上的数据(例如 TinyMCE),您可能需要执行以下技巧

form.addEventListener('submit', function(event)
{
    let form = this;
    let submitter = event.submitter;
    setTimeout(function()
    {
        let formdata = new FormData(form);
        formdata.append(submitter.name, submitter.value);
        xhr.send(formdata);
    }, 0);
    event.preventDefault();
}

setTimeout(..., 0) 将允许所有现有的submit 处理程序运行,并在继续收集 FormData 并发送 XHR 之前将整个事件循环排空。

【讨论】:

    【解决方案3】:

    您可以维护表单,只需添加额外的事件来设置哪个按钮称为提交。

    var form_config = {button: null};
    
    $("#submit1").click(function(){
      form_config.button = 'submit1';  
    });
    
    $("#submit2").click(function(){
      form_config.button = 'submit2';  
    });
    
    $('#testform').submit(function(e) {
        console.log(e);
        e.preventDefault();
    
        var submiturl;
    
        if (form_config.button === 'submit1') { submiturl = '../sendToFactory.cshtml'; }
        else if (form_config.button  === 'submit2') { submiturl = '../sendOverseas.cshtml'; }
        $("#hi").val(submiturl);
    
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <form id="testform">
        <input type="text" id="hi" name="hi" />
        <input type="text" id="bye" name="bye" />
    
        <button type="submit" id="submit1">Use Me</button>
        <button type="submit" id="submit2">No, Use Me </button>
    </form>

    【讨论】:

    • 所以基本上没有办法让 e 参数知道点击了哪个按钮。就是这样吗?
    • 嗯,事件目标将始终是表单,因为这就是事件所关联的。
    • 此代码正在为发生错误而尖叫。我永远不会使用这个。为什么要使用只有 1 个值的对象创建全局变量?为什么不直接将submiturl 的值扔到submit 处理程序内的if 中呢?并且,为了使其最小化可用,您必须将其包装在一个函数中。
    • 对象的原因是因为我假设他想做的事情的复杂性可能是可变的,他可以设置不同的属性等等,使用具有可读性和可理解性的封装数据是一种很好的设计实践编码约定。 “form_config”是表单的配置,真的很简单,你不高兴是因为我没有为这个用例做的吗?我认为您的批评无效。
    • 没有人认为这是一个有趣的答案?如果只能使用提交按钮的点击事件来完成,我们为什么要绑定表单提交事件? @Mike 你为什么要做这样的调整?
    【解决方案4】:

    如果你不使用表单的提交事件,而你需要使用按钮事件触发器,那么你应该这样做:

    $('button').click(function(e){
    var id$ = $(this).attr('id');
    e.preventdefault();
    
    var submiturl;
    
    if (id$ == 'submit1') { submiturl = '../sendToFactory.cshtml'; }
    else if (id$ == 'submit2') { submiturl = '../sendOverseas.cshtml'; }
    
    $.ajax({
        url: submiturl,
        data: $('testform').serialize(),
        type: 'POST',
        datatype: 'json',
        success: function (response) {
            //stuff
        },
        error: function (response) {
            //error
        }
        });
    });
    

    【讨论】:

    • 你从哪里得到$this?为什么要创建一个名为 id$ 的全局变量?
    • $this 是一个由点击事件生成的 jquery 对象。关于全局变量,我将这段代码作为一个例子写得很快,而不是作为一个很好的代码,你显然应该这样做var id$ = ... 注意:$this 是单击按钮的 jquery 元素。
    • Uncaught exception: ReferenceError: Undefined variable: $this 在 Windows XP SP3 x86 上的 Opera 12.17 上使用 jQuery 1.11.0。
    • 我很抱歉你应该使用$(this);我真的写这个代码很快。对不起
    【解决方案5】:

    试试这个

    $(document).ready(function() {
        $( "form" ).submit(function () {
            // Get the submit button element
            var btn = $(this).find("button:focus").val();
            alert(btn);
            //DO YOUR AJAX
        });
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-07
      • 1970-01-01
      • 1970-01-01
      • 2018-03-29
      • 2016-12-01
      相关资源
      最近更新 更多