【问题标题】:Why does modal not works when calling a remote partial in rails?为什么在rails中调用远程部分时模态不起作用?
【发布时间】:2020-05-17 06:23:14
【问题描述】:

基本设置工作:

翻译/_edit_single_translation.html.erb

<div id="modalContent" class="modal-content">
  <div class="modal-header">
    <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
  <div class="modal-body"></div>
  <div class="modal-footer">
    <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
    <button type="button" class="btn btn-primary">Save changes</button>
  </div>
</div>

layouts/application.html.erb 包含:

<%= render 'translations/edit_single_translation' %>

<div id="modal-window" class="modal hide fade modal-backdrop" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div id="modalDialog" class="modal-dialog" role="document">
    Content comes here
  </div>
</div>

链接:

link_to "Translate Link", translations_edit_path(:locale => locale,: key => key), local: true)

这样就可以了

从我删除的 applications.html.erb 中:

&lt;%= render 'translations/edit_single_translation' %&gt;

并将链接更改为:

link_to "Translate Link", translations_edit_path(:locale =&gt; locale,: key =&gt; key), remote: true)

在 javascript/packs/modal-action.js 我放:

$("#modal-window").find(".modal-content").html("<%= j (render partial: 'translations/edit_single_translation') %>");
$("#modal-window").modal('show');

现在它不起作用。

添加时:

alert(\'&lt;%= j (render partial: "translations/edit_single_translation") %&gt;')

到模态动作。我收到了&lt;%= j (render partial: "translations/edit_single_translation") %&gt; 的警报

我错过了什么?

[编辑]

我发现调用了“show”方法。谷歌搜索一两天,我发现不是:

respond_to do |format|
    format.js
    format.html
end

我不得不说:

respond_to do |format|
    format.js { render :layout => false }
    format.html
end

在翻译的“显示”方法中。

然后我不得不搬家

$("#modalDialog").html('<%= j (render partial: 'edit', locals: { items: @translation } ) %>');
$('#modal-window').modal();

javascript/packs/modal-action.jstranslations\show.js.erb

为了进行添加和更新工作,我将所有翻译放在一个跨度中,键为 id。 添加或编辑后更新相应的翻译并关闭我放置的模式:

$('#<%= params[:key].gsub(".","_") %>').html('<%= params[:value] %>');
$('#modal-window').modal('hide');

translations\create.js.erb

$('#<%= params[:i18n_backend_active_record_translation][:key].gsub(".","_") %>').html('<%= params[:i18n_backend_active_record_translation][:value] %>');
$('#modal-window').modal('hide');

translations\update.js.erb 我的添加表单是 form_with,编辑是 form_for

我的translations_controler.erb 包含:

class TranslationsController < ApplicationController
  def index
  end

  def show
    @translation = Translation.find_by(:locale => find_locale,
                                        :key => params[:key])
    @key = params[:key]
    if @translation.nil?
      @Translation = Translation.new
    end
    respond_to do |format|
      format.js { render :layout => false }
      format.html
    end
  end

  def new
  end

  def create
    @translation = Translation.create(translation_create_params)
    respond_to do |format|
      if @translation.save
        I18n.backend.reload!
        format.json { head :no_content }
        format.js
      else
        format.json { render json: @customer.errors.full_messages, 
                            status: :unprocessable_entity }
      end
    end
  end

  def edit
  end

  def update
    respond_to do |format|
      @translation = Translation.find(t_id)
      if @translation.update(translation_update_params)
        I18n.backend.reload!
        format.json { head :no_content }
        format.js { } 
      else
        format.json { render json: @translation.errors.full_messages,
                                   status: :unprocessable_entity }
      end
    end
  end

  private
    def t_id
      params[:i18n_backend_active_record_translation][:id]
    end

    def find_locale
      params[:locale].nil? ? I18n.default_locale : params[:locale]
    end

    def translation_update_params
      params.require(:i18n_backend_active_record_translation).permit(:locale,
      :key, :value)
    end

    def translation_create_params
      params.permit(:locale, :key, :value)
    end
end

现在模态正在工作:) :)。

【问题讨论】:

    标签: javascript jquery ruby-on-rails bootstrap-modal


    【解决方案1】:

    这里有很多混乱。

    资产管道

    放置在资产管道 (Webpacker) 中的 Javascript 在部署时在生产环境中编译。在 Rails 6 中,你把你的“包”——资产清单放在app/javascripts/packs 中。这意味着您从布局链接到的主文件,它需要您正在使用的库以及您的代码。我们鼓励您将自己的应用程序代码放在app/javascripts

    Webpacker 不会通过 ERB 解释器传递 .js 文件,因此期望 $("#modal-window").find(".modal-content").html("&lt;%= j (render partial: 'translations/edit_single_translation') %&gt;") 会输出除字符串 "&lt;%= j (render partial: 'translations/edit_single_translation') %&gt;" 之外的任何内容是完全不现实的。

    与带有 webpacker 的 sprocket 不同,您实际上必须 manually install .js.erb integration。但请记住,该文件仍在部署时编译,而不是在运行时编译,因此上下文将完全错误,您将无法访问帮助程序和查看可让您渲染部分的上下文。

    Rails UJS 和js.erb

    当您在链接和表单上使用data-remote 时,Rails UJS 将发送一个带有application/javascript 内容类型的ajax 请求。然后,您的控制器应该响应 js 并呈现一个 js.erb 视图,然后通过在包含响应的页面上创建一个脚本元素来评估该视图,以便该视图更改现有页面。

    class ThingsController < ApplicationController
      def show
        @thing = Thing.find(params[:id])
        respond_to do |f|
          format.js 
          format.html
        end
      end
    end
    
    // app/views/things/show.js.erb
    el = document.getElementById("#thing");
    el.innerHTML = "<%= j @thing.name %>";
    
    
    

    雅格尼

    如果您只想在模态中渲染部分内容,则实际上不需要首先将模板输出到 JS 中。您可以使用content_for 在您的布局中创建一个占位符,您的视图可以填充:

    <div class="modal fade" id="exampleModalCenter" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenter" aria-hidden="true">
      <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="exampleModalLabel">
              <%= content_for :modal_title %>Modal Title<% end %>
            </h5>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
          <div class="modal-body">
            <%= content_for :modal %><% end %>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
            <button type="button" class="btn btn-primary">Save changes</button>
          </div>
        </div>
      </div>
    </div>
    

    稍后可以在视图中填写内容:

    <% content_for :modal_title, "Edit translation", flush: true %>
    <% content_for :modal do %>
      <%= render partial: 'translations/edit_single_translation' %>
    <% end %>
    

    现在您的 JavaScript 所要做的就是显示模式。

    【讨论】:

    • 好的,这证实了我的警报测试所暗示的内容。所以更进一步。你的解释很棒。因此,如果我理解正确:在展示中,我使用必须填充内容参数的每个内容元素进行布局,并为它们提供唯一的 ID。我用必要的信息在控制器中填充了一个全局变量。我在 show.js.erb 中使用这个全局变量来生成实际上将数据放入布局中的 javascript 代码。
    • 不,不是。 js.erb 模板实际上只是一种懒惰的 ajax 方法,也是您可以采用的一种方法。不要真正“将数据放入布局中”,它是一个脚本,当您运行它时可以更改 DOM。这通常用于在 rails 中将部分输出为 HTML 字符串,然后将其注入到文档(浏览器中的页面)中。
    • content_for 另一方面是所有服务器端。它在缓冲区中创建占位符块,您可以在呈现视图时填充内容。而且您在任何情况下都不需要使用全局变量——您可以通过实例变量或局部变量将变量从控制器传递到视图。
    • 非常感谢您的 cmets。所以更详细地说我想要完成的事情:fi:在注册表单上,我在每个标签后放置一个翻译按钮。当点击时,模式被激活,带有默认语言和当前语言的特定标签的信息,以及更改(或在不存在翻译时添加)当前语言信息的可能性。 (按钮仅在应用处于翻译模式且用户属于当前语言的翻译策略组时出现。)
    • 我发现在方法中format.js 必须替换为format.js { render :layout =&gt; false } 否则.js.erb 将不会加载。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-27
    相关资源
    最近更新 更多