Clev3r
Clev3r

Reputation: 1578

Grails template inheritance

I'm trying to mimic template inheritance as found in Django with a Grails app. I want to be able to define a '_header.gsp' which includes all the shared resources across the app:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>${title}</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    %{--Shared Styles--}%
    <link rel="stylesheet" href="${resource(dir: 'app/shared/css/bootstrap', file: 'bootstrap.min.css')}" type="text/css">

    %{--Shared Libraries--}%
    <script src="${resource(dir: 'lib/jquery', file: 'jquery.js')}"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script>

    %{--View-specific styles--}%
    <g:each var="style" in="${styles}">
        <link rel="stylesheet" href="${style}" type="text/css">
    </g:each>

    %{--View-specific scripts--}%
    <g:each var="include" in="${includes}">
        <script src="${include}" type="text/javascript"></script>
    </g:each>

For each specific view template I will include this _header.gsp with a dictionary to fill in the view-specific requirements:

<g:render template="/header"
          model="[
            title:'Alerts',
            styles:[
                    '${resource(dir: "app/stuff/css", file: "other.css")}',
                    '${resource(dir: "app/stuff/css", file: "second.css")}'
                    ],
            includes:[
                    '${resource(dir: "app/stuff/src/main/js/", file: "app.js")}',
                    '${resource(dir: "app/stuff/src/main/js/", file: "filters.js")}'
                    ]
            ]" />

This is not working, and I'm sure my syntax is wrong somewhere. Can you define a '$resource(dir)' path inside of a g:each like I have? Perhaps I need to use g:link? Can this be done with Grails?

Upvotes: 0

Views: 441

Answers (1)

dspies
dspies

Reputation: 1543

It sounds like you just need to use the resources tag. Define your 'resources' in ApplicationResources.groovy. Then, in your layout include the r:layoutResources tag, and finally, in the gsp specify the resource modules you want to include on that page.

In ApplicationResources.groovy

modules = {

    application {
        dependsOn 'jquery'

        resource url: 'css/other.css'
        resource url: 'css/second.css'
        resource url: 'js/bootstrap.js'
    }

    charting {
        //Charting is dependent on the 'application' resource module above, 
        // so it will include everything from the application and the 
        // charting css and js.
        dependsOn 'application'  

        resource url: 'css/chart.css'
        resource url: 'js/pie-chart.js'
    }

    reports {
        //Completely separate so there is no dependsOn.  
        // Like 'application' module, it will only include the resources below.

        resource url: 'css/pdf.css'
        resource url: 'js/interactive-report.js'
    }
}

In the /grails-app/layouts/main.gsp

<head>
  ...
  <r:layoutResources />
</head>
<body>
  ...
  <r:layoutResources />
</body>

In the /grails-app/views/someDomain/

list.gsp

<head>
  ...
  <r:require modules="application" />
</head>
<body>
  ...

</body>

report.gsp

<head>
  ...
  <r:require modules="reports" />
</head>
<body>
  ...
</body>

charts.gsp

<head>
  ...
  <r:require modules="charting" />
</head>
<body>
  ...
</body>

Upvotes: 2

Related Questions