(Quick Reference)

4 Using resources - Reference Documentation

Authors: Marc Palmer (marc@grailsrocks.com), Luke Daley (ld@ldaley.com), Peter N. Steinmetz (ndoc3@steinmetz.org)

Version: 1.2.13

4 Using resources

Now that you know how to declare resources, you need to use them in your page.

There are several tags for this purpose, but the primary means is to use the require tag to indicate which modules you need, and the layoutResources tag to perform the rendering of the resources.

The require tag causes the framework to look up all the resources required to satisfy your module dependencies. However nothing is rendered at that point.

The layoutResources tag is called to render the resources themselves (and internally it calls into external tag for each resource). This tag has special behaviour, in that the first time you call it, it automatically renders only resources with disposition "head". The second time you call it, it automatically renders only resources with disposition "defer".

4.1 Linking to CSS, JavaScript etc.

So you need to add two calls to layoutResources tag to your GSP page or sitemesh layout. Normally you will place it in your sitemesh layout:

Your grails-app/views/layouts/main.gsp:

<html>
   <head>
      <g:layoutTitle/>
      <r:layoutResources/>
   </head>
   <body>
      <g:layoutBody/>
      <r:layoutResources/>
   </body>
</html>

You can of course include any common modules you require in your sitemesh layout using <r:require> but they must appear before the first <r:layoutResources/>.

In your GSP pages you invoke the require tag as many times as required, even inside GSP templates that you include with g:render, and you can include resources conditionally - something that can be really hard to do without resource dependency management.

Example GSP page:

<html>
   <head>
      <meta name="layout" content="main"/>
      <r:require modules="jquery-ui, blueprint"/>
      <g:if test="${customerBranding}">
          <r:require module="theme_${customer.theme}"/>
      </g:if>
   </head>
   <body>
      <div>
           Hello World
      </div>  
   </body>
</html>

4.2 Linking to images

When you need to render an <img> tag that you wish to be subject to the Resources processing chain (e.g. to make it eternally cacheable) you should use the <r:img> tag:

<r:img uri="images/logo.png" width="100" height="50"/>

<r:img dir="images" file="logo.png" width="100" height="50"/>

Usually this will produce a link to an undeclared resource. However you can declare images in modules and specify extra attributes in "attrs" to supply e.g. the width and height:

modules = {
    images {
        resource url:'images/logo.png', attrs:[width:100, height:50, alt:'Our logo'], disposition:'inline'
        resource url:'images/icon/add.png', attrs:[width:32, height:32, alt:'Add'], disposition:'inline'
    }
}

Once you have done this, using <r:img> to reference them would automatically set the width, height and other attributes.

The disposition "inline" is optional - as long as you don't have any other modules that "dependOn" the images module and link using r:resource or r:img, you won't need this.

4.3 Linking to resources explicitly, bypassing modules

Sometimes you may need to link to a specific resource, or produce a URL pointing to the specific resource without rendering links to all the modules it depends on - or outside of a context where you can call <r:layoutResources/>. You may even wish to link to an undeclared resource, but still want it to be subject to processing on the fly.

To link to CSS or other resources that are not declared in a module you use <r:external>:

<r:external uri="js/custom.js"/>
<script type="text/javascript">
    var urlOfCSSToLoadInJSCode = '${r.external(uri:"css/custom.css").encodeAsJavaScript()}';
</script>
<r:external uri="icons/favicon.ico"/>

This would output the <script> and <link> tags required to include those resources, without rendering their dependencies first - whether the resource is declared in a module or not. The example shows how you might pass the URL of a resource to some JavaScript code for use later at runtime.

4.4 Including pieces of JavaScript code generated at runtime

Often in an application, especially those using custom Grails tags and rich UIs, you will need to render fragments of JavaScript code while the page is being rendered. It is not always possible to know what JS code there will be in the page until the render process is finished.

The script tag allows you to specify sections of JavaScript text during page rendering, but if using Sitemesh layouts, you will be able to have these fragments appear either in <head> or deferred to the end of the page, just like other JavaScript resources.

This integrates with the disposition mechanism, allowing you to throw your JavaScript into a specific location:

<r:script>
    window.alert('This is the end of the page!');
</r:script>

<r:script disposition='head'> window.alert('This is the head of the page!'); </r:script>

What happens is the <r:script> tag stashes your fragment in the request attributes until <r:layoutResources/> is called - when it is pulled out of the attributes and rendered according to the current disposition being rendered.

This is ideal for other custom Grails GSP taglibs to use to write out their JS code used to e.g. set up UI elements:

class MyCustomTagLib {
    def datePicker = {
        out << r.script(disposition:'head') {
            out << '$("#'+attrs.id.encodeAsJavaScript()+').datePicker();'
        }
    }
}

The order of code is preserved, and all such fragments are rendered after all the modules required by the page (in that disposition) have been included.