[Radiant] Shared Layouts

Sean Cribbs seancribbs at gmail.com
Sun Jul 6 12:06:43 CDT 2008


Mohit Sindhwani wrote:
> I have a very simple question about shared_layouts - how do I use it?  
> I saw the readme and it says that it Allows Rails controllers/actions 
> to use Radiant layouts as their "layout".   I already have a Radiant 
> app directory called newsite.  Should I also do a rails newsite so 
> that the default Rails stuff is created there?
>
> I'm sorry this sounds like a real newbie :) but I've either done 100% 
> Rails or done 100% Radiant so far!
Since there seems to be some confusion about how to use share_layouts 
lately, I'll break it down into steps for you and everyone.

1) Create an extension and a controller in it that you want to render 
views within a Radiant layout.

2) Create the layout in the Radiant interface, paying close attention to 
the page parts that you are rendering with the <r:content /> tag.  Example:

<html>
<body>
  <div id="main"><r:content /></div>
  <div id="sidebar"><r:content part="sidebar" /></div>
</body>
</html>

Save that as a layout called 'Two-Column'.

3) Add the radiant_layout declaration to your controller(s), like so:

  radiant_layout 'Two-Column'

In this case, I would be referring to the Radiant layout stored in the 
database called 'Two-Column' that we created above.  There are other 
ways to determine which layout to use, and I'll discuss some of those at 
the end.

4) Now, construct your view to create captured blocks that correspond to 
the page parts.  The default 'yield' or 'content_for_layout' in a Rails 
view corresponds to the Radiant 'body' part.  Example:

<% content_for :sidebar do %>
  <p>This is the sidebar.  It will be rendered inside an r:content tag 
that refers to the 'sidebar' part.</p>
<% end %>

<h1>Hello World!</h1>
<p>This is the main content. It is outside any content_for block but 
will be turned into the 'body' part.</p>

5) Check that your routes are properly defined to point to your 
controller and then hit the appropriate action in your browser. Et 
voila!  Here's what the rendered view might look like:

<html>
<body>
  <div id="main">
    <h1>Hello World!</h1>
    <p>This is the main content. It is outside any content_for block but 
will be turned into the 'body' part.</p>
  </div>
  <div id="sidebar">
    <p>This is the sidebar.  It will be rendered inside an r:content tag 
that refers to the 'sidebar' part.</p>
  </div>
</body>
</html>

That's the basics.

Now, I promised that there were some other tricks, so I ought to explain 
those. 

First, similarly to the Rails 'layout' declaration, you can pass a block 
that will be executed at runtime to determine the proper layout.  A good 
use-case for this would be to specify the layout you want to use in a 
Radiant::Config key.  Example:

radiant_layout { |controller| Radiant::Config['my_extension.layout'] }

Given the controller gets passed in as well, you can monkey with 
whatever you need there, including the path parameters, session, etc.

Second, if you want your controllers to have more context within the 
rest of the site's static content, you can create what I like to call 
"application endpoints".  Essentially, create a page within the page 
tree that is of type 'Application' (classname RailsPage) at a URL that 
matches your controller's route(s).  Then when you hit your controller 
action, anything that is not directly specified by your view or 
controller, including title, breadcrumbs, page parts, etc will be 
derived from the existing page.  This allows you to keep context within 
generated navigation or provide static text within your view that is 
editable from the Radiant UI.  I don't think I have it implemented 
correctly, but ideally one should be able to select a layout on the page 
in the tree and have it set the controller's layout (I'll probably fix 
that today).

Third, you can manually define the title and breadcrumbs from within 
your view or controller.  Setting @title and @breadcrumbs or creating 
content blocks for them will override the title and breadcrumbs for a 
found "endpoint" or define them for a controller without an "endpoint".  
Example:

<% content_for :title do %>My beautiful web page<% end %>
<% content_for :breadcrumbs do %>Home &gt; My beautiful web page<% end %>

Another neat trick you can do with share_layouts is to generate Radius 
code from your controller's views.  Since essentially anything generated 
by the Rails view gets inserted into page parts and then rendered as if 
it were a page, you can put anything you want in there that is valid 
Radius code.  Additionally, if you create an "endpoint" in the tree and 
specify some filters on parts that will be overridden, your view can be 
filtered with those filters.  This means you could write your views in 
Textile, Markdown, or whatever other filter you want!

I know that's a lot to take in, so I'll try to write up a tutorial on 
the wiki for it.  Hope this explanation helps you!

Cheers,

Sean


More information about the Radiant mailing list