Rel dibuat sebagian dengan balok

119

Saya mencoba menggunakan kembali komponen html yang telah saya tulis yang menyediakan gaya panel. Sesuatu seperti:

  <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>

Jadi saya melihat bahwa render membutuhkan satu blok. Saya pikir kemudian saya bisa melakukan sesuatu seperti ini:

# /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>

Dan saya ingin melakukan sesuatu seperti:

#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 %>

Sayangnya ini tidak berfungsi dengan kesalahan ini:

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 -%>
...

Jadi tidak suka yang =jelas dengan blok, tetapi jika saya menghapusnya, maka itu tidak menghasilkan apa-apa.

Adakah yang tahu bagaimana melakukan apa yang saya coba capai di sini? Saya ingin menggunakan kembali panel html ini di banyak tempat di situs saya.

brad
sumber
1
Jawaban yang diterima benar, tetapi karena Rails 5.0.0 hal ini dimungkinkan tanpa layoutsolusi, lihat panduan.rubyonrails.org/…
fabi

Jawaban:

208

Sementara kedua jawaban di atas berfungsi (yah contoh yang ditautkan tony) saya akhirnya menemukan jawaban paling ringkas di posting di atas (komentar oleh Kornelis Sietsma)

Saya kira render :layouttidak persis apa yang saya cari:

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

dikombinasikan dengan:

# /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>
brad
sumber
6
di Rails 3.2.2, saya pikir Anda harus menggunakan <%= %>bukan <% %>, misalnya<%= render :layout => '/shared/panel',
Siwei Shen申思维
Anda benar, posting ini tidak membuat asumsi tentang versi Rails, saya yakin orang bisa mengetahuinya.
brad
seperti ini (menyelesaikan masalah saya jadi +1), tetapi apakah ini praktik yang baik? tidakkah akan ada perlambatan karena alasan tertentu? Mungkin database memicu lebih cepat daripada yang seharusnya karena hasil lain (tidak punya waktu untuk menyelidikinya sendiri sekarang, hanya bertanya-tanya)
setara8
1
Adakah cara untuk mengetahui apakah suatu konten telah dihasilkan? Dalam hal itu opsional.
Vadorequest
3
Di Rails 5.0 ada perubahan jadi ini umum untuk semua parsial, bukan hanya tata letak. Anda dapat mengubah baris pertama kode panggilan menjadi:<%= render '/shared/panel', title: 'some title' do %>
Jay Mitchell
27

Berikut adalah alternatif berdasarkan jawaban sebelumnya.

Buat parsial Anda di 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>

Tentukan metode Anda di application_helper.rb:

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

Sebut saja dari tampilan mana pun:

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

Anda bisa menggunakan pembantu tangkap, dan bahkan sebaris dalam panggilan render:

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

dan di bersama / panel:

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

yang akan menghasilkan:

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

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

Yetanotherjosh
sumber
1
Pola sebaris bagus untuk sebagian yang membutuhkan banyak blok.
mahemoff
4

Berdasarkan jawaban yang diterima, inilah yang bekerja dengan baik untuk saya menggunakan Rails 4.

Kami dapat membuat panel seperti ini:

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

masukkan deskripsi gambar di sini

Ini membutuhkan metode pembantu dan tampilan bersama:

metode pembantu (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

Lihat (/ui/panel.html.haml)

.panel{ class: options[:panel_classes] }
  .panel-heading= heading
  .panel-body
    = yield
Keris
sumber
Ini berfungsi di Rails 5.x juga, saya hanya perlu mengubah panel.html.hamlke_panel.html.haml
Kris
1

Saya pikir itu akan berhasil (baru saja melakukan tes kotor cepat) jika Anda menetapkannya ke variabel terlebih dahulu dan kemudian mengeluarkannya.

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