【问题标题】:Rails use content_for and render the same layout twiceRails 使用 content_for 并两次渲染相同的布局
【发布时间】:2020-03-08 07:33:03
【问题描述】:

我正在使用一个具有非常特定布局的主题,我想为您的 Rails 表单提供一种故障安全方式。

我有一个布局app/views/shared/forms/fields/_layout.html.erb

<div class="js-form-message mb-4">
  <div class="js-focus-state input-group u-form">
    <div class="input-group g-brd-primary--focus">
      <%= yield(:field) %>
    </div>
  </div>
</div>

我有两个部分。 第一部分:app/views/shared/forms/fields/_email.html.erb

<% form = locals[:form] %>
<% locals[:required] = locals[:required].nil? ? true : locals[:required] %>
<% locals[:placeholder] = locals[:placeholder] || t('forms.shared.email.placeholder') %>


<%= render layout: "shared/forms/fields/layout", locals: locals do %>
  <% content_for(:field) do %>
    <%= form.email_field :email, 
      placeholder: locals[:placeholder], 
      class: "form-control g-py-15 g-px-15",
      "data-error-class"=>"u-has-error-v1-3",
      "data-success-class"=>"u-has-success-v1-2",
      "data-msg-email" => t('forms.shared.email.validate'),
      "data-msg" => t('forms.shared.required'),
      autofocus: locals[:autofocus],
      required: locals[:required] %>  
  <% end %>
<% end %>

第二部分:app/views/shared/forms/fields/_login.html.erb

<% form = locals[:form] %>
<% locals[:required] = locals[:required].nil? ? true : locals[:required] %>
<% locals[:placeholder] = locals[:placeholder] || t('forms.shared.login.placeholder') %>


<%= render layout: "shared/forms/fields/layout", locals: locals do %>
  <% content_for(:field) do %>
    <%= form.email_field :login, 
      placeholder: locals[:placeholder], 
      class: "form-control g-py-15 g-px-15",
      "data-error-class"=>"u-has-error-v1-3",
      "data-success-class"=>"u-has-success-v1-2",
      "data-msg" => t('forms.shared.required'),
      autofocus: locals[:autofocus],
      required: locals[:required] %>  
  <% end %>
<% end %>

当我这样做时:

<%= render "shared/forms/fields/email", locals: {form: f} %>

<%= render "shared/forms/fields/login", locals: {form: f} %>

我明白了

Email Field

Email Field/Login Field

我发现content_for '追加' 你给它的块,然后当我yield 时返回整个块。

第一次在content_for(:field) 中没有任何内容,它附加到Email Field。但是第二次它并没有清除它的内容,只是将Login Field附加到它上面。

我正在考虑为layout.html.erb 增加额外的复杂性,因此仅将其保持内联不是一种选择。

有没有办法告诉布局只产生 content_for 的“最新”值。

编辑:

我写了一个yield后flush的方法,提示会再次使用相同的key:

def yield_and_flush!(content_key)
  view_flow.content.delete(content_key)
end

【问题讨论】:

    标签: html ruby-on-rails layout ruby-on-rails-5


    【解决方案1】:

    content_forflush 选项来重置以前的内容:

    <% content_for :field, flush: true do %>
       new content here
    <% end %>
    

    【讨论】:

    • 这不起作用,因为我添加了一个 :after_field。这意味着如果第一个刷新它之前的所有内容,然后第二个没有 :after_field 内容。然后将呈现第一个的内容。我需要在内容呈现后会刷新的东西。
    • @Mihailhidr0Kirilov 您可以使用&lt;%= content_for(field_name) %&gt; 手动渲染,然后使用flush 重置
    • 这就是我所做的,但使用了 yield_and_flush!方法。 @Vasfed
    【解决方案2】:

    解决方案是编写一个yield_and_flush! 方法。看到了解决方案here

    def yield_and_flush!(content_key)
      view_flow.content.delete(content_key)
    end
    

    【讨论】:

    • 使用 Rails 指南中未提及的 Rails 内部 API 不是一个好习惯,因为这可以在任何 Rails 版本中被破坏,甚至是次要/补丁,没有任何弃用警告等。跨度>
    • 我同意。你有其他解决方案吗?我写了关于行为的测试,我希望从长远来看,这会让我保持检查。
    • 您可以在这里使用我的回答中的公共 api - content_for(content_key).tap{ content_for(content_key, '', flush: true) }
    猜你喜欢
    • 2011-09-19
    • 1970-01-01
    • 2017-06-01
    • 2011-05-09
    • 1970-01-01
    • 2011-01-02
    • 1970-01-01
    • 2010-11-10
    • 2013-07-24
    相关资源
    最近更新 更多