Rails,render_async gem:如何在通过 ajax 加载的部分中使用 render_async [英] Rails, render_async gem: How to use render_async inside a partial that is loaded via ajax

查看:67
本文介绍了Rails,render_async gem:如何在通过 ajax 加载的部分中使用 render_async的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题

我正在使用 gemrender_async"异步渲染内容.

当我访问像 localhost:3000/people 这样的页面时,内容会按预期异步呈现.

但是,如果内容位于通过 ajax 加载的部分中,则不会异步呈现内容.我不明白为什么它不起作用,我不知道如何修复它.

如何使用 render_async,如果它在通过 ajax 加载的部分中?

gem render_async:https://github.com/renderedtext/render_async

什么有效

当我调用像 localhost:3000/people 这样的索引页面时,render_async 按预期工作.

这是有效的代码:

people/index.html.erb

人物

...<div class="人"><%= 渲染部分: "people/show", collection: people, as:person %>

在 people-div 中,部分 _show.html.erb 正在加载.

people/_show.html.erb

人员

...<%= render_async render_shared_pa​​th(parent_type: "Person", parent_id: person.id), 'data-turbolinks-track': 'reload', error_message: '<p>对不起,用户加载出错:(</p>'做%>共享 lädt!<%结束%>

此代码按预期工作.render_async 加载名为 _children.html.erb 的部分.当用户访问 people/index.html.erb 时,所有 _children-partials 都被异步加载.

什么不起作用

在 people/index.html 上,当用户按下按钮时,people-div 将通过 ajax 重新加载.以下是重新加载人员 div 的方式:

var people_div = ".people";$( people_div ).fadeOut( "fast", function() {content = $("<%= escape_javascript( render 'people/people', people: @people ) %>")$(people_div).replaceWith(function(){返回 $(content).hide().fadeIn("fast");});});

正在重新加载的代码与 people/index.js 中的代码相同.只有参数发生了变化.

在 people-div 重新加载后,不会异步渲染任何内容._children-partials 未加载.rails 控制台或 Web 控制台中没有消息.

唯一可见的是占位符:Shared lädt!".

可能是什么问题?

代码

_show.html.erb

 <%= render_async render_shared_pa​​th(parent_type: "Person", parent_id: person.id), 'data-turbolinks-track': 'reload', error_message: '<p>对不起,用户加载去了错误:(</p>'做%>共享 lädt!<%结束%>

routes.rb

 #renderget '/render_shared', to: 'render#render_shared', as: 'render_shared'

render_controller.rb

 def render_sharedparent_type = params[:parent_type]parent_id = params[:parent_id]@parent = parent_type.singularize.classify.constantize.find(parent_id)呈现部分:共享/孩子"结尾

_children.html.erb

<% parent = parent ||@父%><div class="shared-<%=parent.class.name.downcase%>-<%=parent.id%>"><p><a class="btn btn-link btn-sm" data-toggle="collapse" href=".address-<%= parent.id %>-<%= parent.class.to_s.downcase %>"role="button" aria-expanded="false" aria-controls="collapseExample"><%= fa_icon "地址卡" %>访问地址</a></p><div class="折叠 mb-2 地址-<%= parent.id %>-<%= parent.class.to_s.downcase %>"><%= render "addresses/show", address: parent.address %>

application.html.erb

 <title>MyApp</title><%= csrf_meta_tags %><%= csp_meta_tag %><%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %><%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %><%= content_for :render_async %>

解决方案

在深入研究这个问题后,问题似乎出在 render_async 的 Vanilla JS 部分.Vanilla JS 不评估来自父 render_async 响应的脚本标签.

作为快速修复,我建议您尝试使用 render_async 的 jQuery 部分,因为它确实会评估脚本标签.您可以通过执行以下操作来打开 jQuery:

RenderAsync.configure 做 |config|config.jquery = true # 这将渲染 jQuery 代码,并跳过 Vanilla JS 代码结尾

说明

当您尝试渲染嵌套的部分时,render_async 会在脚本标记内加载 JS 代码,该标记需要进行评估才能执行另一个请求.jQuery 有一个强大的方法 .replaceWith(text) ,它评估文本变量中的任何脚本标签.这在普通 JS 中并不容易实现.我正在为此想出一个解决方案.

如果有人知道如何实现这一点,您可以在此 GitHub 问题上做出贡献 https://github.com/renderedtext/render_async/issues/30

Problem

I'm using the gem "render_async" to render content asynchronously.

When I visit a page like localhost:3000/people, the content gets rendered asynchronously, as expected.

However, the content does not get rendered asynchronously, if it is inside a partial that got loaded via ajax. I don't understand why it isn't working and I don't know how to fix it.

How can I use render_async, if it is inside a partial that got loaded via ajax?

gem render_async: https://github.com/renderedtext/render_async

What works

When I call an index page like localhost:3000/people, render_async works as expected.

Here is the code that works:

people/index.html.erb

<h1>People</h1>
...
    <div class="people">
        <%= render partial: "people/show", collection: people, as: :person %>
    </div>

Inside the people-div, the partial _show.html.erb is being loaded.

people/_show.html.erb

<h1>Person</h1>
...
 <%= render_async render_shared_path(parent_type: "Person", parent_id: person.id), 'data-turbolinks-track': 'reload', error_message: '<p>Sorry, users loading went wrong :(</p>' do %>
      Shared lädt!
 <% end %>

This code works as expected. The render_async loads a partial called _children.html.erb. When a user visits people/index.html.erb, all _children-partials are being loaded asynchronously.

What doesn't work

On people/index.html, when the user presses a button, the people-div is being reloaded via ajax. Here is how the people div is being reloaded:

var people_div = ".people";

$( people_div ).fadeOut( "fast", function() {

    content = $("<%= escape_javascript( render 'people/people', people: @people ) %>")

    $(people_div).replaceWith(function(){
      return $(content).hide().fadeIn("fast");
    });

});

The code that is being reloaded is the same as in people/index. Only the params change.

After the people-div is reloaded, no content gets rendered asynchronously. The _children-partials are not being loaded.There are no messages in the rails console or in web console.

The only thing that is visible is the placeholder: "Shared lädt!".

What might be the problem?

Code

_show.html.erb

    <%= render_async render_shared_path(parent_type: "Person", parent_id: person.id), 'data-turbolinks-track': 'reload', error_message: '<p>Sorry, users loading went wrong :(</p>' do %>
      Shared lädt!
    <% end %>

routes.rb

  #render
  get '/render_shared', to: 'render#render_shared', as: 'render_shared'

render_controller.rb

  def render_shared
    parent_type = params[:parent_type]
    parent_id = params[:parent_id]

    @parent = parent_type.singularize.classify.constantize.find(parent_id)

    render partial: "shared/children"

  end

_children.html.erb

<% parent = parent || @parent %>

<div class="shared-<%=parent.class.name.downcase%>-<%=parent.id%>">
  <p>
    <a class="btn btn-link btn-sm" data-toggle="collapse" href=".address-<%= parent.id %>-<%= parent.class.to_s.downcase %>" role="button" aria-expanded="false" aria-controls="collapseExample">
      <%= fa_icon "address-card" %> Adresse anzeigen
    </a>
  </p>

  <div class="collapse mb-2 address-<%= parent.id %>-<%= parent.class.to_s.downcase %>" >
    <%= render "addresses/show", address: parent.address %>
  </div>

</div>

application.html.erb

  <head>
    <title>MyApp</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
    <%= content_for :render_async %>
  </head>

解决方案

After looking more into this issue, the problem seems to be in the Vanilla JS part of render_async. Vanilla JS doesn't evaluate script tags that come from the parent render_async response.

As a quick fix, I suggest that you try to use jQuery part of render_async, since it does evaluate script tags. You can turn on jQuery by doing:

RenderAsync.configure do |config|
  config.jquery = true # This will render jQuery code, and skip Vanilla JS code
end

Explanation

When you try to render a nested partial, render_async loads JS code inside a script tag that needs to be evaluated to do another request. jQuery has a powerfull method .replaceWith(text) which evaluates any script tags in the text variable. This is not so easy to achieve in plain JS. I'm trying to come up with a solution for this.

If anyone has an idea how to achieve this, you can contribute at this GitHub issue https://github.com/renderedtext/render_async/issues/30

这篇关于Rails,render_async gem:如何在通过 ajax 加载的部分中使用 render_async的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆