【问题标题】:Unobtrusive-JS function not triggering when new records deleted when using jQuery-ujs with Rails使用带有Rails的jQuery-ujs时删除新记录时不触发Unobtrusive-JS功能
【发布时间】:2018-05-28 20:23:36
【问题描述】:

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 来确认是否正确执行。有什么想法吗?

【问题讨论】:

    标签: jquery ruby-on-rails ajax ujs


    【解决方案1】:

    您的问题是 javascript 侦听器绑定到 &lt;li&gt; 标记,而不是实际链接。监听器从来没有机会开火。

    我个人会更改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();
    }); 
    

    【讨论】:

    • 正在返回正在删除的教程,以便我可以渲染它并使用 ajax:success 方法来获取它,但是您的解决方案更加整洁 - 只需使用 event.target 然后记录删除不需要传递。
    • 坏消息是,即使在我实施了更改后,我的行为也相同,但您指出了正确的方向 - 这是 jQuery 事件绑定未更新的问题,我需要使用根据此解决方案委派事件:stackoverflow.com/a/17453051/9154357 我正在跟进此事,当我弄清楚到底发生了什么时会更新。
    • 好的,知道了。该错误与事件委托有关 - 这是必要的,因为我要隐藏的“li”元素在页面加载时不存在,因此它从未绑定到它的隐藏事件。 html 页面中的 'ul' 元素的标题应为 &lt;ul id="tutorials"&gt;,jQuery 函数应为 $('#tutorials').on(...。感谢@Thomas R. Koll 的帮助,你说得对,'li' 元素有些可疑。
    • 如果render json: {success: true}不知道要隐藏的对象的ID,它如何有机会触发?
    • @Jerome 我不能 100% 确定我是否可以回答您的问题:它不需要知道 id。 $(event.target).closest('li') 有点粗糙,但可以胜任。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 2018-07-02
    相关资源
    最近更新 更多