-
Notifications
You must be signed in to change notification settings - Fork 20
Template inheritance
The template inheritance pattern allows you to use templates in a modular fashion. It consists of:
-
A base "view" template that contains the skeletal markup of your site and defines placeholders and blocks that child templates can override.
-
A base "viewModel" template that sets up common variables and default content, and loads child viewModel templates on demand when specific functionality is required. Child viewModules are considered to be discrete, self-contained, reusable modules.
In the following example we're using a custom field to optionally choose a 'widget' (child viewModel) to format the page content. The child vM extends the parent vM and can load it's own partial layouts into blocks, and/or overload placeholder variables in the parent view.
work
index.html
layouts
standard.html
viewmodels
page_vm.html
projects_vm.html
partials
project_list.html
project_detail.html
Loads the primary viewModel, compiles and caches the rendered templates as a variable, using the page URI as the context.
{stash:embed
context="@URI"
name="page_vm"
file_name="viewmodels:page_vm"
parse_stage="both"
stash:_status="open"
stash:_channel="pages"
stash:_layout="standard"
}
{stash:embed context="layouts" name="{stash:_layout}"}
{!-- capture entry data --}
{exp:channel:entries
channel="{stash:_channel}"
status="{stash:_status}"
limit="1"
disable="member_data|pagination|categories"
{if segment_2} require_entry="yes"{/if}
}
{if no_results}
{redirect="site/404"}
{/if}
{!-- standard entry fields --}
{exp:stash:set type="snippet"}
{stash:pg_title}{title}{/stash:pg_title}
{stash:pg_entry_id}{entry_id}{/stash:pg_entry_id}
{stash:pg_url_title}{url_title}{/stash:pg_url_title}
{/exp:stash:set}
{!-- custom entry fields --}
{exp:stash:set type="snippet"}
{stash:pg_intro}{page_intro}{/stash:pg_intro}
{stash:pg_body}{page_body}{/stash:pg_body}
{/exp:stash:set}
{!-- load a widget (child viewModel)? --}
{exp:switchee variable="{page_widget}" parse="inward"}
{case value="#^S+#"}
{!-- load the associated viewModel for the widget --}
{exp:stash:embed
context="viewmodels"
name="{page_widget}_vm"
process="inline"
replace="yes"
}
{/case}
{/exp:switchee}
{/exp:channel:entries}
{exp:switchee variable="{segment_3}" parse="inward"}
{!-- project listing --}
{case value=""}
{!-- load the project_list layout into the pg_content block --}
{exp:stash:extend name="pg_content" with="partials:project_list"}
{exp:stash:set_list
name="projects"
parse_tags="yes"
}
{exp:channel:entries
channel="projects"
status="open"
disable="member_data|pagination|categories"
dynamic="no"
}
{stash:project_title}{title}{/stash:project_title}
{stash:project_url_title}{url_title}{/stash:project_url_title}
{/exp:channel:entries}
{/exp:stash:set_list}
{/case}
{!-- project detail --}
{case default="yes"}
{!-- load the project_detail layout into the pg_content block --}
{exp:stash:extend name="pg_content" with="partials:project_detail"}
{!-- get project data --}
{exp:channel:entries
channel="projects"
status="{stash:_status}"
limit="1"
disable="member_data|pagination|categories"
url_title="{segment_3}"
dynamic="no"
require_entry="yes"
}
{if switchee_no_results}
{redirect="site/404"}
{/if}
{exp:stash:set type="snippet"}
{!-- override the heading in the main layout --}
{stash:pg_title}{title}{/stash:pg_title}
{!-- capture project custom fields for use in the project_detail partial --}
{stash:project_image}{project_image}{/stash:project_image}
{/exp:stash:set}
{/exp:channel:entries}
{!-- prev/next entry links --}
{exp:channel:next_entry
channel="projects"
status="{stash:_status}"
url_title="{segment_3}"
parse="inward"
}
{exp:stash:set name="project_next_url" type="snippet"}{url_title}{/exp:stash:set}
{/exp:channel:next_entry}
{exp:channel:prev_entry
channel="projects"
status="{stash:_status}"
url_title="{segment_3}"
parse="inward"
}
{exp:stash:set name="project_prev_url" type="snippet"}{url_title}{/exp:stash:set}
{/exp:channel:prev_entry}
{/case}
{/exp:switchee}
<!DOCTYPE html>
<html>
{sn_head}
<body>
<h1>{pg_title}</h1>
<div class="content">
{exp:stash:block name="pg_content"}
{if pg_intro}<p class="intro">{pg_intro}</p>{/if}
{pg_body}
{/exp:stash:block}
</div>
{sn_footer}
</body>
</html>
<ul class="list list--projects">
{exp:stash:get_list name="projects"}
<li><a href="/{segment_1}/{segment_2}/{project_url_title}">{project_title}</a></li>
{/exp:stash:get_list}
</ul>
<img src="{project_image}" alt="">
<a href="{project_prev}">Previous</a> | <a href="{project_next}">Next</a>
Getting started
Using Stash
Using Mustash
- Mustash
- Installing Mustash
- Managing variables
- Managing bundles
- Cache-breaking rules
- Mustash plugins
- Mustash Varnish plugin
- Mustash plugin development
- Mustash API
Template design patterns
Tag reference
- {exp:stash:set}
- {exp:stash:get}
- {exp:stash:block}
- {exp:stash:set_value}
- {exp:stash:append}
- {exp:stash:append_value}
- {exp:stash:prepend}
- {exp:stash:prepend_value}
- {exp:stash:copy}
- {exp:stash:context}
- {exp:stash:is_empty}
- {exp:stash:not_empty}
- {exp:stash:set_list}
- {exp:stash:get_list}
- {exp:stash:append_list}
- {exp:stash:prepend_list}
- {exp:stash:split_list}
- {exp:stash:join_lists}
- {exp:stash:list_count}
- {exp:stash:unset}
- {exp:stash:flush_cache}
- {exp:stash:bundle}
- {stash:embed}
- {exp:stash:extend}
- {exp:stash:parse}
- {exp:stash:cache}
- {exp:stash:static}
- {exp:stash:finish}
- {exp:stash:not_found}
- Short tag syntax
- Using Stash methods in your own add-ons