cells icon indicating copy to clipboard operation
cells copied to clipboard

Access content cell from external layout

Open Scharrels opened this issue 9 years ago • 2 comments

The only way to communicate between an external layout and its content is through the yield call, while an internal layout can call all content cell methods.

This patch adds the @option[:content_cell] option to layout cells and provides the Cell::Viewmodel::Layout::External::Content interface for communication between an external layout cell and the content cell it wraps. This interface is convenient if you want to create standard components (e.g. for bootstrap) that have multiple content areas, such as a panel. With this interface, such a layout cell can be defined as follows:

module Layout
  module Cell
    class Panel < Trailblazer::Cell
      include ::Cell::ViewModel::Layout::External::Content

      def footer?
        !content_block(:footer).nil?
      end
    end
  end
end

The layout itself pretty straightforward (in this case, i'm using erb):

<div class="panel panel-default">
  <div class="panel-heading">
    <%= content_block(:title) { "Default title" } %>
  </div>
  <div class="panel-body"><%= yield %></div>
  <% if footer? %>
      <div class="panel-footer"><%= content_block(:footer) %></div>
  <% end %>
</div>

The Cell::ViewModel::Layout::External interface provides thecontent_block(:method)method. This method checks if the content cell defines:method. You can provide a block that will be rendered if it doesn't. If you don'tnilwill be returned. You can render aSongCell` with this layout as follows:

class Song
  module Cell
    class SongCell < ::Trailblazer::Cell
      include ::Cell::ViewModel::Layout::External
      property :song_title
      property :author
      property :year

      def title
        song_title
      end

      def footer
        render "song/footer"
      end
    end
  end
end

song.erb:

<p><strong>Author:</strong> <%= author %></p>
<p><strong>Year:</strong> <%= year %>

song/footer.erb:

<a href="edit">Edit this song</a>

This patch is completely backwards compatible: all it does is providing the @option[:content_cell] option by default to layout cells. The content_block functionality is not provided by default; it is completely separated in the ::Cell::ViewModel::Layout::External module.

This interface is also useful for a full-page layout. Webpages often need a customized page title and footer. Without this patch, you could only customize this context by adding it to the @options[:context] option. With this patch, you can directly define this content in your cells.

Scharrels avatar Jun 06 '16 13:06 Scharrels

What if other cells would simply write to the context object?

apotonick avatar Jul 09 '16 02:07 apotonick

I thought again about this: why don't we simply provide the content cell instance in the :context object? That would save the new argument and utilize what's already there.

context[:content_cell] # set per default

What do you think, will that do the trick?

apotonick avatar Jul 10 '16 07:07 apotonick

So, about this 8 years old change...

Long story short: the remote repository of this pull request is a company account, Scharrels does not work here anymore, and we've refactored our web framework so that we have no more need of this change. If anybody is still interested in adding the proposed updates to this change: please make a copy of the branch and do so. Otherwise' we'd rather remove our fork of this repository (which will close the PR).

herwinw avatar Mar 26 '24 11:03 herwinw

No worries @herwinw, thanks for thinking of us :beers:

apotonick avatar Mar 26 '24 11:03 apotonick