(Quick Reference)

7 Themes API - Reference Documentation

Authors: Marc Palmer (marc@grailsrocks.com)

Version: 1.0.RC2

7 Themes API

Themes are collections of Sitemesh layouts that follow conventions for template locations and Resource modules, with support for multiple content "zones" per page.

Themes define the visual layout of pages rendered by your application and plugins. The views in a plugin or application can choose to use a theme layout using the layout tag instead of the normal <meta> tag to select the Sitemesh layout. So for users of Themes, Sitemesh layouts are no longer explicitly used.

You can search the Grails plugin repository for plugins that provide off the shelf Themes that your application can use.

As a theme author, using the theme namespace tags you can create themes that will allow Grails applications and plugins to define their UI largely without any concern for the structural page layout itself - and swap the visual styling without changing the code of the GSPs.

Optionally working together with UI Sets, applications and plugins can then leverage whatever UI technology a theme was written with - because the Theme determines the UI Set to use for the current request.

The end result is that the application or users can change the Theme on a per request or user basis, and the structural HTML markup, the CSS, the Javascript and all other resources will be adapted to suit the Theme.

For example you might have a user-centric site front end that uses a custom theme style by in-house designers using raw jQuery, and a simple back end admin theme that is based directly on Twitter Bootstrap and custom JS code.

The Theme system is inspired by efforts such as the Wordpress theme community, where you can take an off the shelf theme that instantly styles your site, but may also add extra non-standard features - some of which may follow conventions across other themes.

By formalising some of these conventions - for example by using UI Sets to represent the commonly themed components of a site - we allow our plugin ecosystem to rely on a core set of functionality from themes, while avoiding raising the bar too high and being over-prescriptive.

Highly stylized themes will inevitably need extra configuration, custom tags or style conventions to get high quality results. Application content may still need to be written to fit the available space in a theme. Colours may need to be tweaked.

However it should all be a lot quicker, and more fun.

7.1 Using Themes In Your Application

Using Platform UI Themes in your Grails applications is simple.

There are only three things you need to do:

  1. Provide a theme implementation
  2. Tell Platform UI which of the standard theme layouts your GSP requires
  3. Define your content zones

Providing a Theme implementation

Out of the box there is a default theme called _default. This will be used if you don't provide your own. It is deliberately minimal

You can provide a Theme by either installing a Theme plugin (a standard Grails plugin containing a theme), or by creating your own Theme.

Most real apps will supply their own Theme, or a forked version of a Theme from a plugin.

To create your own theme see the Creating Themes. Scripts are provided to fork existing themes or create new plain ones.

You don't need to tell the app which Theme to use at this stage because it will default to the first non-default theme you have installed, or fall back to the _default theme.

Telling Platform UI which Theme Layout to use

Each GSP that uses Themes needs to use the layout tag to specify which of the Theme's layouts applies to the page.

This is easily done in the <head> section of your views:

<html>
   <head>
      <theme:layout name="home"/>
   </head>
   .
   .
   .
</html>

You can parameterize this if you need to present different layouts based on some runtime variables.

Defining your Content Zones

Now that you have chosen a layout for your GSP, you need to provide the content for the zones defined by that layout.

Zones are chunks of content your page supplies, that the Theme layout will position for you according to its styling.

At the very least all pages have a "body" zone.

See the Zone Requirements section for details of the zones supported by each required layout.

You define the content for a zone using the zone tag. Note that if you only need to supply a body, you do not need to use this tag, but if you are supplying multiple zones, all content including that for the body zone must be wrapped in zone tags:

<html>
    <head>
      <theme:layout name="home"/>
    </head>
    <body>   
        <theme:zone name="body">
            <p>Welcome to our site</p>
        </theme:zone>
        <theme:zone name="panel1">
            <p>Marketing text 1</p>
        </theme:zone>
        <theme:zone name="panel2">
            <p>Marketing text 2</p>
        </theme:zone>
        <theme:zone name="panel3">
            <p>Marketing text 3</p>
        </theme:zone>
    </body>
</html>

Note that your view does not have to supply content for every zone. There is fallback algorithm that allows your Application and the Theme to provide default content for zones, and as a last resort falling back to Lorem Ipsum filler text. Theme layouts can also adapt to the absence of content for some zones.

See the documentation for the zone tag and Creating Themes for more details of the zone mechanism and behaviour for location content.

7.2 Content Zones

Themes use zones to pull in multiple pieces of content to build up the page.

All layouts usually need a zone for the "body" content, but they may also have others for e.g. a sidebar or promotional areas.

Theme layouts determine the structural HTML of the page, and where the content for each zone is rendered using the layoutZone tag.

The GSP pages themselves use the zone tag to define the content to be used in a given zone.

How content for zones is resolved

Content for the zone is resolved in this order:

  1. Content defined by the page being rendered, using the zone:themeTags tag
  2. If the zone is "body" the page body is used (using the default g:layoutBody tag)
  3. If the application supplies a GSP fragment in /grails-app/views/_themes/zones/<zone-name>.gsp this is used
  4. Finally the defaultContent tag is used to provide default content, which will check if the Theme itself provides default content, and failing that the default Platform UI theme. If there is still no default content GSP it will revert to p:dummyText from Platform Core to render some Lorem Ipsum-style text.

Through this cascade of content resolution your application can provide default content for zones such as header/footer, or fall back to theme defaults - and even use application or theme defaults for e.g. footer but override these on a page-by-page basis if necessary.

Setting the content for a given zone from within your GSP page

You do this using the zone tag:

<html>
    <head>
        <theme:layout name="home"/>
    </head>
    <body>
        <theme:zone name="body">
            <p>This is the body of my page</p>
        </theme:zone>

        <theme:zone name="banner">
            <ui:h1>Our Awesome Startup!</ui:h1>
        </theme:zone>

        <theme:zone name="panel1">
            <p>Read about the features you're going to love...</p>
        </theme:zone>

        <theme:zone name="panel2">
            <p>Find our more about our pricing model</p>
        </theme:zone>

        <theme:zone name="panel3">
            <p>Tell us what you think</p>
        </theme:zone>
    </theme:body>
</html>

Note that if a page only requires a body zone you can omit the zone tags and just specify body content as normal.

Appending more content to a zone

It is possible to append content to a zone, for example a sidebar may contain information from various sources.

You can do this by defining a zone multiple times, or by directly accessing the grailsThemes bean to add content to a given zone.

For example you may have plugins that add filters to append content to such zones automatically.

Themes can provide default content for zones

Themes can and should provide attractive default content for the zones used in the layouts.

This allows a user to see how best to use that particular theme because out of the box all the zones are populated, perhaps with example graphics etc.

7.3 About The _default Theme

The Platform UI plugin does supply a single default Theme and UI Set called _default.

There are however not intended for use. They simply exist to provide some form of rendering of content when there is no other Theme or UI Set available.

As such the UI Set does not have a useful implementation of all UI tags, in particular the ui:field, ui:tabs and ui:carousel tags are incomplete.

UI Sets should not rely on the content of these templates as a default fallback, and should instead always supply all the templates they require.