Rails UJS通过更改隐藏输入值来调用ajax

时间:2016-07-12 20:51:13

标签: ruby-on-rails ajax

我有一个隐藏的输入字段,其中包含必要的数据属性以使用Rails UJS ajax支持:

<%= hidden_field_tag 'step-value', 0, data: { remote: true, url: comments_path, method: :get, params: "commentable_id=#{@contact.id}&commentable_type=#{@contact.class.demodulized_name}&user_id=#{current_user.id}", type: :html } %>
<div class="input-group-content form-control-static">
  <div id="slider-step" class="ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all"><span class="ui-slider-handle ui-state-default ui-corner-all" tabindex="0" style="left: 0%;"></span>
  </div>
</div>

documentation表示您可以将“data-url”和“data-remote”应用于表单元素,当表单元素的值更改时,将触发ajax调用。

隐藏的输入字段不是这样。我通过javascript更改了隐藏的输入字段:

$("#slider-step").slider({value: 0, min: 0, max: 1, step: 1,
  slide: function (event, ui) {
    $('#step-value').val(ui.value);
  }
});

永远不会进行ajax调用。如何使用Rails UJS触发带隐藏表单元素的ajax调用?

1 个答案:

答案 0 :(得分:0)

这其实很简单。我在github阅读了rails.js的代码。

首先,它定义了一个名为inputChangeSelector的成员变量,这将使用数据远程属性监听表单控件选择器上的特定事件:

inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]',

现在我们附加到这些选择器的事件使用自定义事件和事件命名空间的概念。在此处denoted,我们可以创建on事件以附加到on()委托上的选择器,然后使用trigger()方法触发这些事件。

$( ".lightbulb" ).on( "light:toggle", function( event ) {
    var light = $( this );
    if ( light.is( ".on" ) ) {
        light.removeClass( "on" ).addClass( "off" );
    } else {
        light.removeClass( "off" ).addClass( "on" );
    }
});

$( ".switch, .clapper" ).click(function() {
    var room = $( this ).closest( ".room" );
    room.find( ".lightbulb" ).trigger( "light:toggle" );
});

此解决方案比使用.switch或.clapper选择器上的内置点击事件更优雅,因为我们将灯泡的行为保持在灯泡元素中,而不是将其与其他元素混合。

另一点是命名空间,如described所示。事件名称可以由事件名称空间限定,以简化删除或触发事件。例如,“click.myPlugin.simple”定义了此特定click事件的myPlugin和简单命名空间。可以使用.off(“click.myPlugin”)或.off(“click.simple”)删除通过该字符串附加的单击事件处理程序,而不会干扰附加到元素的其他单击处理程序。

因此,对于Rails UJS库,它将以下事件附加到具有data-remote属性的表单控件:

$document.delegate(rails.inputChangeSelector, 'change.rails', function(e) {
  var link = $(this);
  if (!rails.allowAction(link) || !rails.isRemote(link)) return rails.stopEverything(e);

  rails.handleRemote(link);
  return false;
});

那我怎么解雇这个事件呢?简单:

    $("#slider-step").slider({value: 0, min: 0, max: 1, step: 1,
        slide: function (event, ui) {
            $('#step-value').val(ui.value);
            $('#step-value').trigger('change.rails');
        }
    });

它有效。