Give Your Clients Control Of Their Sidebar

This tutorial shows a way to allow your clients to control which sidebar elements appear on which page, with drag-and-drop reordering, using only a Global Content Block and AdvancedContent.

Smarty is one of the ingredients that makes CMSMS truly configurable. Often, we need to change our sidebars depending on which page we are on. For example, on our Blog page, we might not want our latest blog entries in the sidebar, and replace it with something else. Smarty provides a way to control this:

{if $page_alias == 'blog'}
  {* Show another sidebar element *}
  {* Show the Blog sidebar element *}

The issue is that while this is easy for us, it's not all that flexible, and your clients will make a mess of it if you give them template access. If the site increases to hundreds of pages, the above code can get quite messy. There is a very easy way to allow your clients to click checkboxes and re-order them on a page-per-page basis.

Setting the default blocks and order

Let's create a Global Content Block called 'sidebar_order' that contains the list (and order) of our sidebar elements. These will just contain brief names that describes the functions. When creating this GCB, click off 'Use WYSIWYG' (version 1.9+) not 'Turn WYSIWYG on/off' which is slightly different.


This indicates that we want a blog, calendar and FEU login for the webmaster to choose from, in that order.


In my opinion, AdvancedContent is the best module in the Forge. Regular {content} allows us to define multiple content blocks, but {AdvancedContent} allows us to present checkboxes, multiselects, etc. to the page editor, and define presets for these. We're going to use this module to define a multiselect to allow the webmaster to decide which sidebar elements can be on which page. Install AdvancedContent, (see note at bottom before installing) then go to Extensions -> AdvancedContent in the control panel and click on 'Set all Pages of type Content to type Advanced Content.'. This will change all 'content' pages to now be 'AdvancedContent'. For some reason, you can't have AdvancedContent be the default page type, so you have to remember to switch each page to AdvancedContent upon new page creation.

Let's create our 'sidebar_element' AdvancedContentBlock. Insert the following tag into your template, right after the <body> tag:

{content block='sidebar_elements' block_type='select_multiple' label='Sidebar Elements' assign='sidebar_elements' items=":::global_content name=sidebar_order:::" default=":::global_content name=sidebar_order:::" delimiter=',' page_tab='options' smarty='true' sortable_items='true'}

Note that we're using {content} instead of {AdvancedContent}. For some reason, the latest version doesn't like the 'sortable_items' parameter, and will give you an error when you use it. Since your page is of AdvanceContent content type, this will still work.

Let's pick the above tag apart to understand what we're doing:

This is the internal name of the content block in the database.

This is the type. Normally 'select_multiple' gives you a multi-select list box.

label='Sidebar Elements'
The title that the editor sees.

Put the choices that the webmaster selected in a Smarty variable with this name.

items=":::global_content name=sidebar_order:::"
The list of items to choose from. We have our list in a GCB. You can't use {ldelim} {rdelim} inside of a tag. AdvancedContent uses ':::' to designate a smarty command.

default=":::global_content name=sidebar_order:::"
This indicates which ones we want selected by default. Since it's the same GCB, we are saying we want all selected. If you want a different list, use a different GCB.

Normally '|' is the default delimiter.. We're using a comma.

We don't want this on the main tab. Not expected to change often.. Put it at the bottom of the 'Options' tab. Give it a new name, and it will create new tab for it.

Indicates that 'items' and 'default' have Smarty in it. Don't take it literally.

We want this list to be sortable. It changes the multi-select listbox to checkboxes, with drag-and-drop capabilities.. Drag the arrows.


The Template

Now to put this all together. In your template, let's write some Smarty code where your sidebar normally is:

{assign var='sidebar_elements' value=','|explode:$sidebar_elements}
{foreach from=$sidebar_elements item='element'}

  {if $element == 'blog'}
    {* Latest Blog sidebar stuff goes here *}

  {if $element == 'calendar'}
    {* Upcoming Events sidebar stuff goes here *}

  {if $element == 'login'}
    {* The Login box goes here *}


Pretty easy. The above code turns the comma separated list 'sidebar_elements' (remember assign=sidebar_elements above?) into an array, then does a foreach on them. It spits out the keywords (block, calendar, login) in the order that the editor chose, then presents the HTML/smarty code that belongs to that keyword.


Now let's put it to work. Edit (or create) a page. Click on 'Options', scroll to the bottom, click on and off which elements you want for this page. If you want to change the order, drag the arrows and drop the element where you want. Click on Submit and you're done! One note. All new pages get this property. All the existing pages will have a blank sidebar. You have to edit each page, then 'Submit' and the defaults will be saved.


A new version (0.7.2) was released. I installed it and it broke everything. All content blocks were hidden (collapsed), and the defaults didn't work. I reverted back to 0.7.1, then filed a bug report.