Skip to content

Template inheritance

Mark Croxton edited this page Jun 20, 2013 · 37 revisions

Essentially this pattern allows you to extend parent view and viewModel templates with child templates loaded on the fly. Views contain block elements that render default content.

In the following example we're using a custom field to optionally choose a 'widget' (child viewModel) for a page content. The child VM extends the parent VM and can load it's own partial layout and overload fields in the parent view.

EE templates

work
   index.html

Stash templates

layouts    
   standard.html
viewmodels    
   page_vm.html    
   projects_vm.html    
partials
   project_list.html    
   project_detail.html    

/templates/default_site/work.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_templates/viewmodels/page_vm.html

{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}{/exp:low_replace}{/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}

/stash_templates/viewmodels/projects_vm.html

{exp:switchee variable="{segment_3}" parse="inward"}

    {!-- project listing --}
    {case value=""}

        {!-- load the project_list layout into the pg_content block --}
        {exp:stash:set name="pg_content"}{exp:stash:embed:partials:project_list}{/exp:stash:set}

        {exp:stash:set_list 
            name="projects" 
            parse_tags="yes" 
        }
            {exp:channel:entries 
                channel="projects"
                status="open" 
                disable="member_data|pagination|categories"
                dynamic="off"
            }
                {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:set name="pg_content"}{exp:stash:embed:partials:project_detail}{/exp:stash:set}

        {!-- get project data --}
        {exp:channel:entries 
            channel="projects"
            status="{stash:_status}" 
            limit="1" 
            disable="member_data|pagination|categories"
            url_title="{segment_3}"
            dynamic="off"
	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}

/stash_templates/layouts/page.html

    <!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>

/stash_templates/partials/project_list.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>

/stash_templates/partials/project_detail.html

    <img src="{project_image}" alt="">
    <a href="{project_prev}">Previous</a> | <a href="{project_next}">Next</a>
Clone this wiki locally