Đường ray hiển thị một phần với khối


119

Tôi đang cố gắng sử dụng lại một thành phần html mà tôi đã viết để cung cấp kiểu bảng điều khiển. Cái gì đó như:

  <div class="v-panel">
    <div class="v-panel-tr"></div>
    <h3>Some Title</h3>
    <div class="v-panel-c">
      .. content goes here
    </div>
    <div class="v-panel-b"><div class="v-panel-br"></div><div class="v-panel-bl"></div></div>
  </div>

Vì vậy, tôi thấy rằng kết xuất có một khối. Tôi nghĩ sau đó tôi có thể làm điều gì đó như thế này:

# /shared/_panel.html.erb
<div class="v-panel">
  <div class="v-panel-tr"></div>
  <h3><%= title %></h3>
  <div class="v-panel-c">
    <%= yield %>
  </div>
  <div class="v-panel-b"><div class="v-panel-br"></div><div class="v-panel-bl"></div></div>
</div>

Và tôi muốn làm điều gì đó như:

#some html view
<%= render :partial => '/shared/panel', :locals =>{:title => "Some Title"} do %>
  <p>Here is some content to be rendered inside the panel</p>
<% end %>

Rất tiếc, điều này không hoạt động với lỗi này:

ActionView::TemplateError (/Users/bradrobertson/Repos/VeloUltralite/source/trunk/app/views/sessions/new.html.erb:1: , unexpected tRPAREN

old_output_buffer = output_buffer;;@output_buffer = '';  __in_erb_template=true ; @output_buffer.concat(( render :partial => '/shared/panel', :locals => {:title => "Welcome"} do ).to_s)
on line #1 of app/views/sessions/new.html.erb:
1: <%= render :partial => '/shared/panel', :locals => {:title => "Welcome"} do -%>
...

Vì vậy, nó không thích =rõ ràng với một khối, nhưng nếu tôi loại bỏ nó, thì nó sẽ không xuất ra bất cứ thứ gì.

Có ai biết cách làm những gì tôi đang cố gắng đạt được ở đây không? Tôi muốn sử dụng lại html bảng điều khiển này ở nhiều nơi trên trang web của mình.


1
Câu trả lời được chấp nhận là đúng, nhưng vì Rails 5.0.0 này là nếu không có sự layout-workaround, xem guides.rubyonrails.org/...
fabi

Câu trả lời:


208

Mặc dù cả hai câu trả lời đó ở trên đều hoạt động (cũng là ví dụ mà tony liên kết đến), cuối cùng tôi đã tìm thấy câu trả lời ngắn gọn nhất trong bài đăng trên (nhận xét của Kornelis Sietsma)

Tôi đoán render :layoutthực hiện chính xác những gì tôi đang tìm kiếm:

# Some View
<%= render :layout => '/shared/panel', :locals => {:title => 'some title'} do %>
  <p>Here is some content</p>
<% end %>

kết hợp với:

# /shared/_panel.html.erb
<div class="v-panel">
  <div class="v-panel-tr"></div>
  <h3><%= title -%></h3>
  <div class="v-panel-c">
    <%= yield %>
  </div>
</div>

6
trong Rails 3.2.2, tôi nghĩ rằng bạn phải sử dụng <%= %>thay vì <% %>, ví dụ:<%= render :layout => '/shared/panel',
Siwei Shen申思维

bạn nói đúng, bài đăng này không đưa ra giả định nào về phiên bản Rails, tôi chắc rằng mọi người có thể hiểu được điều đó.
brad

như thế này (giải quyết vấn đề của tôi nên +1), nhưng phương pháp này có tốt không? sẽ không có một số chậm lại vì một số lý do? Có lẽ cơ sở dữ liệu trigger sớm hơn nó giả sử vì năng suất khác (không có thời gian để điều tra mà theo bản thân mình bây giờ, chỉ tự hỏi)
equivalent8

1
Bất kỳ cách nào để biết nếu một nội dung đã được sản xuất? Trong trường hợp của nó là tùy chọn.
Vadorequest

3
Trong Rails 5.0 đã có một sự thay đổi vì vậy điều này là chung cho tất cả các thành phần chứ không chỉ bố cục. Bạn có thể thay đổi dòng đầu tiên của mã gọi to:<%= render '/shared/panel', title: 'some title' do %>
Jay Mitchell

27

Đây là một giải pháp thay thế dựa trên các câu trả lời trước đó.

Tạo một phần của bạn trên shared/_modal.html.erb:

<div class="ui modal form">
  <i class="close icon"></i>
  <div class="header">
    <%= heading %>
  </div>
  <div class="content">
    <%= capture(&block) %>
  </div>
  <div class="actions">
    <div class="ui negative button">Cancel</div>
    <div class="ui positive button">Ok</div>
  </div>
</div>

Xác định phương pháp của bạn trên application_helper.rb:

def modal_for(heading, &block)
  render(
    partial: 'shared/modal',
    locals: { heading: heading, block: block }
  )
end

Gọi nó từ bất kỳ chế độ xem nào:

<%= modal_for('My Title') do |t| %>
  <p>Here is some content to be rendered inside the partial</p>
<% end %>

11

Bạn có thể sử dụng trình trợ giúp chụp và thậm chí nội dòng trong lệnh gọi hiển thị:

<%= render 'my_partial',
           :locals => { :title => "Some Title" },
           :captured => capture { %>
    <p>Here is some content to be rendered inside the partial</p>
<% } %>

và trong bảng / chia sẻ:

<h3><%= title %></h3>
<div class="my-outer-wrapper">
  <%= captured %>
</div>

sẽ tạo ra:

<h3>Some Title</h3>
<div class="my-outer-wrapper">
  <p>Here is some content to be rendered inside the partial</p>
</div>

Xem http://api.rubyonrails.org/classes/ActionView/Helpers/CaptureHelper.html


1
Mô hình nội tuyến là tốt cho một phần cần nhiều khối.
mahemoff

4

Dựa trên câu trả lời được chấp nhận, đây là những gì hoạt động tốt với tôi khi sử dụng Rails 4.

Chúng tôi có thể kết xuất một bảng điều khiển như vậy:

= render_panel('Non Compliance Reports', type: 'primary') do
  %p your content goes here!

nhập mô tả hình ảnh ở đây

Điều này yêu cầu một phương thức trợ giúp và một chế độ xem được chia sẻ:

phương thức trợ giúp (ui_helper.rb)

def render_panel(heading, options = {}, &block)
  options.reverse_merge!(type: 'default')
  options[:panel_classes] = ["panel-#{options[:type]}"]

  render layout: '/ui/panel', locals: { heading: heading, options: options } do
    capture(&block)
  end
end

Xem (/ui/panel.html.haml)

.panel{ class: options[:panel_classes] }
  .panel-heading= heading
  .panel-body
    = yield

Điều này cũng hoạt động trong Rails 5.x, tôi chỉ cần thay đổi panel.html.hamlthành_panel.html.haml
Kris

1

Tôi nghĩ rằng nó sẽ hoạt động (vừa thực hiện nhanh chóng kiểm tra bẩn) nếu bạn gán nó cho một biến trước và sau đó xuất nó ra.

<% foo = render :partial => '/shared/panel', :locals =>{:title => "Some Title"} do %>
<p>Here is some content to be rendered inside the panel</p>
<% end %>
<%= foo %>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.