当使用带有Rails的jQuery-ujs时删除新记录时,不会触发Unobtrusive-JS函数

时间:2018-05-28 20:23:37

标签: jquery ruby-on-rails ajax ujs

Rails:5.2.0,Ruby:2.4.1p111,浏览器:Chrome 66.0.3359.181,jquery-rails gem:4.3.3,Turbolinks已禁用。

我正在关注这个AJAX on Rails with Unobtrusive JS教程并且已经到了最后,但有一些我无法弄清楚的奇怪行为。

该应用程序使用UJS允许用户通过AJAX将新记录添加到列表底部,而不必像Rails那样更新整个页面。添加新记录工作正常,但是当我点击“删除”时,application.js中的JS函数不会被触发,所以似乎什么也没发生,但是当我刷新页面时,记录就消失了。如果我添加一条新记录,刷新页面然后尝试删除记录JS被触发并立即从列表中删除/删除记录。

网页非常简单:

<!––  index.html.erb ––> 
<h1>Tutorials</h1>

<ul id=tutorials>
  <%= render @tutorials %>
</ul>

<%= form_with model: Tutorial.new, data: {'js-tutorial-form' => true} do |form| %>
  Title <%= form.text_field :title %><br>
  URL <%= form.text_field :url %><br>
  <%= form.submit %>
<% end %>

有一小部分:

<!––  _tutorial.html.erb ––> 
<li data-js-tutorial-id=<%= tutorial.id %>>    
  <%= tutorial.title %> <%= link_to "Delete", tutorial, remote: true, method: :delete %>
</li>

所有JS都在application.js文件中

$(document).ready(function() {
  $('[data-js-tutorial-form]').on("ajax:success", function(event, data, status, xhr){
    var tutorial = $(xhr.responseText).hide();
    $('#tutorials').append(tutorial);
    tutorial.fadeIn(2000);
  });

     $('[data-js-tutorial-id]').on("ajax:success", function(event, data, status, xhr){
    var tutorial_id = xhr.responseJSON.id;
    $('[data-js-tutorial-id=' + tutorial_id + ']').hide();

  }); 

});

唯一的其他文件是控制器

class TutorialsController < ApplicationController

    def index
        @tutorials = Tutorial.all
    end

    def create
        @tutorial = Tutorial.new(params[:tutorial].permit(:title, :url))
        if @tutorial.save
                render partial: "tutorial", locals: {tutorial: @tutorial}
        end
    end

    def destroy
        @tutorial = Tutorial.find(params[:id])
        @tutorial.destroy
        render json: @tutorial
    end

end

我没有得到的是,在刷新页面之前和之后HTML源代码是相同的,但我已经确认使用Chrome开发人员工具$('[data-js-tutorial-id]')除非页面刷新,否则不会被调用。我在控制器中使用了byebug来确认是否正确地进行了操作。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

您的问题是javascript侦听器绑定到<li>标记,而不是实际链接。听众从来没有机会开枪。

我个人更改destroy方法,为什么要返回刚删除的教程?

def destroy
  @tutorial = Tutorial.find(params[:id])
  @tutorial.destroy
  render json: {success: true}
end

其次,你的部分看起来不对,但没有测试

<!––  _tutorial.html.erb ––> 
<li>    
  <%= tutorial.title %> <%= link_to "Delete", tutorial, remote: true, method: :delete, "data-js-delete": tutorial.id %>
</li>

当然需要更改javascript:

$('[data-js-delete]').on("ajax:success", function(event, data, status, xhr){
  $(event.target).closest('li').hide();
});