With Blocks
The {#with} tag shifts local scope to a sub-object for the duration of its block. Tags inside bind directly against that sub-object.
Basic syntax
{#with Path.To.Subobject}
…tags here bind against the subobject…
{/with}Inside the block, $ refers to the with-target. Bare bind expressions resolve against it, and ..\ walks back to the enclosing scope (see Scope Chain Walk).
Example
Data:
var account = new
{
Person = new
{
Name = new { First = "John", Last = "Doe" },
Address = new
{
Line1 = "112 Main St.",
Line2 = "Suite 210",
City = "Plano",
State = "TX",
Zip = "75075"
},
Employer = "Hat Trick Labs"
}
};Template:
<div>Active Account:</div>
{#with Person.Name}
<div>{First} {Last}</div>
{/with}
<div>Address:</div>
{#with Person.Address}
<div>{Line1}{#if Line2}</br>{Line2}{/if}</div>
<div>{City}, {State} {Zip}</div>
{/with}Result:
<div>Active Account:</div>
<div>John Doe</div>
<div>Address:</div>
<div>112 Main St.</br>Suite 210</div>
<div>Plano, TX 75075</div>Without the scope shift, Person.Address. would repeat on each of the six tags in the block.
Why use {#with} over compound binds
Two practical wins:
- Less repetition — when half a dozen tags all live under the same path, shifting once eliminates the noise of repeating the path on each tag.
- Reusable sub-templates — a sub-template has no knowledge of the parent context; it only needs to know the shape of the
{#with}target. An address fragment knows{Line1},{City},{State},{Zip}and nothing else — wrap it in any{#with}pointing at an address-shaped object and it works regardless of what the parent template is bound to.
This composes well with Partials — a partial authored against a flat scope can be invoked from anywhere by wrapping the call in a {#with}.
Targeting falsy values
If the with-expression is falsy, the block is not rendered. See Core Concepts for the full falsy ruleset.
To render an “absent” message when the with-target is falsy, pair it with {#if !Path}:
{#with Person.Address}
<address>{Line1}, {City}</address>
{/with}
{#if !Person.Address}
<p>No address on file.</p>
{/if}Reaching the outer scope
Inside a {#with} block, the parent scope is one level back. Reach it via ..\:
{#with Person.Address}
{City}, {State} — {..\Person.Name.First}'s address
{/with}Or declare a variable in the outer scope first if the outer value is needed in multiple places. See Scope Chain Walk for the tradeoff.
Nesting
{#with} blocks can be nested freely and combined with {#if}, {#each}, and partials. Each {#with} contributes one level to the scope chain (and one frame to the stack-depth budget — see Stack Depth Limit).
Whitespace
Like other block tags, {#with} accepts - trim markers and is affected by engine-level TrimWhitespace. See Whitespace Control.
Next steps
- Partials — compose reusable fragments that lean on
{#with}for scope shaping - Scope Chain Walk — walk back out of a with-target
- Variables — name an outer value once and reuse it from any nested block