Skip to content
johnideal edited this page Aug 6, 2014 · 3 revisions

This guide covers how to use the Portlets extend the functionality of your BrowserCMS site. The target audience for this guide is developers who are familiar with Rails. You should also read the User's Manual as well, so you know how to create pages and put content on pages. This guide will cover:

  • How to create custom portlets
  • Allowing portlets views to be editable via the UI.

This guide is for BrowserCMS 4.0.

h2. Creating A Portlet

Once you have created the product content block and created a few products in the content library, you need a way to display them on a page. To do that, you will want to create a portlet.

A portlet is a type of content block used to display dynamic data on a page (usually other content blocks). A portlet will typically perform some kind of database query in the render method and then render it's view. One difference between a portlet and typical content block is that each instance of a portlet can have a view template that is editable via the CMS admin interface. Let's generate a portlet to display the most recently created products:

# Rails 3:
$ rails generate cms:portlet recent_products limit:integer

What you will see created is:

  • A portlet at app/portlets/recent_products_portlet.rb
  • A form partial at app/views/portlets/recent_products/_form.html.erb
  • A render template at app/views/portlets/recent_products/render.html.erb
  • A test unit at test/unit/portlets/recent_products_portlet_test.rb ( if you're using Rails 3)

What you don't see created is a migration. Portlets use the DynamicAttributes behavior in order to store associated values in the database without having to create custom database tables. What this means is that you can set and then store a value for any attribute for a portlet.

So if you look at the form partial that was generate for this portlet, you will see this:

<%= f.cms_text_field :name %>
<%= f.cms_text_field :limit %>
<%= f.cms_template_editor :template %>

Every portlet instance has to have a name and that is stored in the main portlets table, but limit is stored in the portlet_attributes table. You could add anything to this form, such as <%= f.cms_text_field :foobar %>, and whatever the user enters for foobar would get saved with the portlet.

If you look at the code for the portlet, you will see:

class RecentProducts < Portlet

  enable_template_editor false

  def render
    # Your Code Goes Here
  end
    
end

As the comment says, you will want to fill in your application logic here. We're going to get the most recent products and use the value the user entered for limit when they filled out the form. So edit the render method to look like:

class RecentProducts < Portlet
    
  def render
    @products = Product.all(:order => "created_at desc", :limit => self.limit)
  end
    
end

self in this case is the portlet instance, which is also available in the instance variable @portlet.
We are setting the @products instance variable so that will be available in the view. If you look at the render template, you will see this:

<%=h @portlet.name %>

This is simply a place holder, you should override this code with how you want the portlet to display. In this case, let's go with:

<ul>
  <% @products.each do |product| %>
    <li><%=h product.name %></li>
  <% end %>
</ul>

Note that with Rails 3 you need to remove the h method because it becomes default on Rails 3.

Allowing template editing via the UI

By default, each instance of a Portlet will render itself using the contents of it's 'render.html.erb' file, because 'enable_template_editor' was marked false. If you look back at the form partial that was generated, you'll see:

<%= f.cms_template_editor :template %>

This is the editing control for the Portlet's template, which will not appear on CMS UI by default. This allows you to quickly refine how you want the default view to look. Once you like the layout for a portlet, you can enable the editor like so:

class RecentProducts < Portlet
  enable_template_editor true
end

Now each instance of the RecentProducts can have its own unique template. Each time a new portlet is created, the contents of the 'render.html.erb' will be copied into the template attribute of the portlet and used to display the portlet. Users can update these views as they see fit.

Gotcha: It's important to remember that once a portlet has a saved template, it will ignore what's in the render.html.erb. So changes made there won't be reflected until the portlet's template has been updated again.

Default Template Handlers

By default, templates are treated as erb views. The template editor has a drop down that allows users to choose other types like 'builder' or 'rhtml'. To set the default handler to something other than erb, modify the _form.html.erb to the following:

<%= f.cms_template_editor :template, :default_handler=>"builder" %>

Alternative handlers for non-editable templates

If the template_editor is disabled, you can also set the handler directly on the portlet like so:

  class RecentProducts < Portlet
    enable_template_editor false
    handler "builder"
  end

Using HAML templates

The default list of handlers does not include Haml. To do that, install the HAML gem and set the default_value to 'haml' like so:

<%= f.cms_template_editor :template, :default_handler=>"haml" %>
Clone this wiki locally