23

While setting up a site recently I wanted to route a specific entry in a structure section to its own custom template. Using a dynamic route sounded like the right option until I remembered that it wouldn't work due to Craft's routing order (matched entry uri comes before matched template).

I considered adding a conditional redirect to the structure's generic template but this feels a bit dirty. Does anyone have a better solution of how to make this work?

Ben Croker
  • 7,341
  • 26
  • 55

3 Answers3

44

The cleanest way I have found to achieve this is to create a generic template for the structure as well as a custom template for each entry that needs one, ensuring that its path matches the entry's uri.

I then put this single line of code in the structure's selected template and it works beautifully:

{% extends [entry.uri, '_generic'] %}

This should work as well:

{% include [entry.uri, '_generic'] %}

If the entry's uri exists as a template route then it will be rendered, otherwise the generic template will be.

UPDATE:

I recently extended this on a site to allow for unique custom pages, custom entry type pages and a fallback generic page:

{% extends [
    '_custom/' ~ entry.slug,
    '_entrytypes/' ~ entry.type,
    '_generic'
] %}
Ben Croker
  • 7,341
  • 26
  • 55
  • 3
    That's very clever! Per the Twig docs, "The first template that exists will be used as a parent". http://twig.sensiolabs.org/doc/tags/extends.html#dynamic-inheritance – Lindsey D Jun 12 '14 at 19:46
  • 2
    In my opinion, this should be marked as the best answer. You may also want to share this "recipe" on http://craftcookbook.net/ – Lindsey D Jun 12 '14 at 20:23
  • Im having a bit of a problem managing this method where the entry.uri file needs to extend blocks in the main file. Any ideas? – Steve Adams Jun 30 '14 at 17:58
  • no, not in the scenario above – Ben Croker Dec 17 '14 at 19:26
  • If your entries are in Structure, and some pages need to use different template, you can use this code in your 'main' template defined in section settings. {% extends [ craft.request.path, '_generic' ] %} – Yuri Salimovskiy Feb 24 '17 at 14:20
5

Currently, the conditional redirect is the best way. You can use it to load a template dynamically in the structure's generic _entry template using the include tag.

My suggestion would be to add a lightswitch field that tells the entry to load a custom template. Then in the _entry template do something like this:

{% if entry.customTemplate %}
    {% include "section/_" ~ entry.slug %}
{% else %}
    {% include "section/_generic" %}
{% endif %}

This is the same basic idea used in Pixel & Tonic's help page on using different templates for different entry types.

Bryan Redeagle
  • 4,065
  • 13
  • 27
  • thanks bryan, this is close to what i did except that i managed to drop the conditional and use an array in the include in its place. – Ben Croker Jun 12 '14 at 20:02
1

I think you are on the right track. Call the generic template _route.html, and have it do nothing but {%extends ...%} to route to the template you want.

Marion Newlevant
  • 12,047
  • 22
  • 55