-
Notifications
You must be signed in to change notification settings - Fork 261
[v4.0] Portlets
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.
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.
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" %>
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
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" %>