:具有多个提交按钮的远程表单

时间:2022-11-24 20:16:01

I can't seem to get a :remote form with multiple submit controls to work under Rails 3. The following code:

我似乎无法获得:具有多个提交控件的远程表单在Rails 3下工作。以下代码:

<%= form_tag({:action => 'debug'}, {:remote => true}) do %>
  <%= submit_tag "Foo" %>
  <%= submit_tag "Bar" %>
<% end %>

Produces a form with two buttons, but the resulting AJAX POST doesn't contain a commit parameter to say which one was pressed. If I leave :remote => true out, the normal POST does contain the commit parameter.

生成一个带有两个按钮的表单,但生成的AJAX POST不包含一个提交参数来说明按下了哪一个。如果我离开:remote => true out,普通POST确实包含commit参数。

Is there any way to make this work, or is it just a bug?

有没有办法让这项工作,或者它只是一个错误?

2 个解决方案

#1


1  

After some playing about, I think I've found a solution.

经过一番游戏后,我想我找到了解决方案。

The problem is that rails.js uses serializeArray() on the form element containing the clicked submit control; but the form's serialized data doesn't contain that control. However, JQuery or Javascript is keeping track of the original event in the call-chain, which was technically a "submit" event on the appropriate control.

问题是rails.js在包含单击的提交控件的表单元素上使用serializeArray();但表单的序列化数据不包含该控件。但是,JQuery或Javascript正在跟踪调用链中的原始事件,这在技术上是适当控件上的“提交”事件。

So I've edited rails.js as follows:

所以我编辑了rails.js如下:

callRemote: function (e) {   /* Note - new parameter e */
            var el      = this,
                method  = el.attr('method') || el.attr('data-method') || 'GET',
                url     = el.attr('action') || el.attr('href'),
                dataType  = el.attr('data-type')  || 'script';

            if (url === undefined) {
              throw "No URL specified for remote call (action or href must be present).";
            } else {
                if (el.triggerAndReturn('ajax:before')) {
                    var data = el.is('form') ? el.serializeArray() : [];
                    /********************/
                    /* Note new if-test */
                    /********************/
                    if (e)
                    {
                        data.push({name: e.originalEvent.explicitOriginalTarget.name,
                        value: e.originalEvent.explicitOriginalTarget.value})
                    }
                    /* Function continues as before */

... and further down ...

......再往下......

$('form[data-remote]').live('submit', function (e) {
    $(this).callRemote(e);
    e.preventDefault();
});

This has the effect of adding in the name-value pair of the clicked button before firing off the AJAX.

这具有在触发AJAX之前添加单击按钮的名称 - 值对的效果。

I'm a bit new to Javascript, so do let me know if any of this is horrendously wrong!

我对Javascript有点新鲜,所以如果这有任何可怕的错误,请告诉我!

#2


1  

I tried your solution and it worked for Firefox, but then the application did not work any more for IE and Safari. Now I found another solution: Simply putting the value of the submit button into a hidden input field by a small javascript.

我尝试了你的解决方案,它适用于Firefox,但随后应用程序不再适用于IE和Safari。现在我找到了另一种解决方案:只需通过一个小的javascript将提交按钮的值放入隐藏的输入字段中。

<input id="selected_button" type="hidden" name="commit" value=""/>
<script>
  function identify_button( el ) {
    window.document.getElementById( 'selected_button' ).value = el.value;
  }
</script>
<input class="button"
       type="submit"
       name="commit"
       value="Save"
       onclick="identify_button( this )" );"
/>
<input class="button"
       type="submit"
       name="commit"
       value="OK"
       onclick="identify_button( this )" );"
/>

#1


1  

After some playing about, I think I've found a solution.

经过一番游戏后,我想我找到了解决方案。

The problem is that rails.js uses serializeArray() on the form element containing the clicked submit control; but the form's serialized data doesn't contain that control. However, JQuery or Javascript is keeping track of the original event in the call-chain, which was technically a "submit" event on the appropriate control.

问题是rails.js在包含单击的提交控件的表单元素上使用serializeArray();但表单的序列化数据不包含该控件。但是,JQuery或Javascript正在跟踪调用链中的原始事件,这在技术上是适当控件上的“提交”事件。

So I've edited rails.js as follows:

所以我编辑了rails.js如下:

callRemote: function (e) {   /* Note - new parameter e */
            var el      = this,
                method  = el.attr('method') || el.attr('data-method') || 'GET',
                url     = el.attr('action') || el.attr('href'),
                dataType  = el.attr('data-type')  || 'script';

            if (url === undefined) {
              throw "No URL specified for remote call (action or href must be present).";
            } else {
                if (el.triggerAndReturn('ajax:before')) {
                    var data = el.is('form') ? el.serializeArray() : [];
                    /********************/
                    /* Note new if-test */
                    /********************/
                    if (e)
                    {
                        data.push({name: e.originalEvent.explicitOriginalTarget.name,
                        value: e.originalEvent.explicitOriginalTarget.value})
                    }
                    /* Function continues as before */

... and further down ...

......再往下......

$('form[data-remote]').live('submit', function (e) {
    $(this).callRemote(e);
    e.preventDefault();
});

This has the effect of adding in the name-value pair of the clicked button before firing off the AJAX.

这具有在触发AJAX之前添加单击按钮的名称 - 值对的效果。

I'm a bit new to Javascript, so do let me know if any of this is horrendously wrong!

我对Javascript有点新鲜,所以如果这有任何可怕的错误,请告诉我!

#2


1  

I tried your solution and it worked for Firefox, but then the application did not work any more for IE and Safari. Now I found another solution: Simply putting the value of the submit button into a hidden input field by a small javascript.

我尝试了你的解决方案,它适用于Firefox,但随后应用程序不再适用于IE和Safari。现在我找到了另一种解决方案:只需通过一个小的javascript将提交按钮的值放入隐藏的输入字段中。

<input id="selected_button" type="hidden" name="commit" value=""/>
<script>
  function identify_button( el ) {
    window.document.getElementById( 'selected_button' ).value = el.value;
  }
</script>
<input class="button"
       type="submit"
       name="commit"
       value="Save"
       onclick="identify_button( this )" );"
/>
<input class="button"
       type="submit"
       name="commit"
       value="OK"
       onclick="identify_button( this )" );"
/>