MasterPages and UserControls
Unlike ASPX pages, string templates don't have the concept of MasterPages and UserControls. On the contrary, they're constructed with the idea that each template doesn't care what "kind" of template it is, it only cares about rendering itself.
Sub-templates : The User Control Equivalent
Much like a user control, an external template can be nested inside of any template. Let's use the example of a navigational menu. Take the following HTML page, and the subsequent template file:
views/home/index.st
<html>
<head>
<title>$title$</title>
</head>
<body>
<div id="Menu">
$shared/menu()$
</div>
<div>
$content$
</div>
</body>
</html>
views/shared/menu.st
<div>
<b>Menu</b>
<a href="/page1">Page 1</a>
<a href="/page2">Page 2</a>
<a href="/page3">Page 3</a>
</div>
When the parser hits line 7 above, it will render the contents of the template at "/views/shared/menu.st". Sub-templates are included by using the construct of $()$. Templates can be nested to any level.
Passing arguments to a sub-template
Arguments from any template can be passed down to sub templates. Let's take a look at an example. Let's pretend we wanted to reuse our menu control, but wanted to add the option to put another link at the bottom for certain pages. First, we add a variable call to our menu file.
views/shared/menu.st
<div>
<b>Menu</b>
<a href="/page1">Page 1</a>
<a href="/page2">Page 2</a>
<a href="/page3">Page 3</a>
$missingLink$
</div>
Now from the calling template, we can simply pass in arguments in the following ways...
straight text
$shared/menu(
missingLink={<a href="/page4">Page 4</a>
})$
passing only a ViewData variable
$shared/menu( missingLink=missingLinkVariable )$
Notice: When passing a variable from ViewData, you can skip the braces.
passing both
$shared/menu(
missingLink={
<a href="$missingLinkVariable$">Missing Link</a>
}
)$
The Master Page Equivalent
So, given the previous sections, you may have already figured out how to do a "master page", or "layout". Just in case you haven't yet, I'll go over it here. First, we'll take a simple layout...
views/shared/master.st
<html>
<head>
<title>$title$</title>
</head>
<body>
<div>$content$</div>
</body>
</html>
Notice the variable placeholders for "title" and "content". You can define as many of these placeholders as you'd like, and name them anything. If variables are not specified by the calling template, the engine will just ignore them. Notice that calling a locally scoped variable is no different than calling an object from the ViewData dictionary. Here's what the child template might look like...
views/home/about.st
$shared/master(
title={
About Us!
}
,content={
<div>This content will be passed to the master page
in a variable called "content".</div>
}
)$
As you can see, the entire template is a sub-template call. When you render the child template, the first thing it does is load the sub-template, and fill in the holes. As it uses the same construct as the "include" sub-template calls, you can nest them "up" the chain as many levels as "down" the chain. This gives you a massive amount of flexibility in terms of template reuse.