Applying a master page template in Sling with HTL

322 views Asked by At

Is there any simple way to apply a page template to multiple Apache Sling scripts?

I'm looking for something akin to the JSP 2.0 Tag option. However, I'm using HTL, which doesn't support such tags.

I could, of course, use HTL includes, such as data-sly-include="${'header.html'}, but these would then have to be manually included in every page I then create.

Ideally I'd like to be able to have a master page containing the layout, which is then automatically applied to all pages of specified resource types, leaving a customisable area for content specific to each resource. I'd then be able to limit my add.html, edit.html, html.html (etc) files to include only a block of code for the content section of the page, preventing unnecessary duplication of layout code across multiple files.

I thought I might be able to achieve this by creating a master page resource (e.g. "page"), then setting sling:resourceSuperType on the individual resources but since this acts as a fallback, it'll only kick in if there's no matching script for the sling:resourceType - and there will be such scripts.

2

There are 2 answers

0
Spinner On BEST ANSWER

I ended up using the following approach:

  1. Add a new resource type page
  2. Create a Sightly/HTL template file for the page resource type (/apps/page/html.html); this is the 'master' page template
  3. Include common elements in that template
  4. Within that template, call the 'child' templates by adding the view selector through the following HTL element: <div data-sly-resource="${request.pathInfo @ selectors='view', addSelectors=request.requestPathInfo.selectors, requestAttributes=request.requestParameterMap}">
  5. For each sling:resourceType that's to be rendered as a page, add a view subfolder (/apps/example_type/view) and place its HTL templates within that folder (e.g. add.html, html.html)
  6. On each resource that should be rendered with the master template, set sling:resourceSuperType to page

When a request comes in to, for example, /content/example_type_instance.add.html, Sling resolution will therefore try to find a script in /apps/example_type/add.html; there isn't one, so it falls back to the resourceSuperType script in apps/page/html.html, which in turn will use the script in /apps/example_type/view/add.html.

This seems to work for the moment. @Vlad's approach with a Sling ResourceDecorator may be more elegant.

2
Vlad On

You could use a Sling Decorator to wrap your resources so that they always get handled by the common scripts before everything else. This way you can impose the template and include the actual resource to fill in the actual values/blocks/custom scripts.

Another option would be to impose a (nested) content tree where the root points to the template scripts (using JCR type, for example) while the children/content point to the custom scripts (using resource type). This is pretty much what AEM does with cq:Page and its jcr:content.