DoneJS StealJS jQuery++ FuncUnit DocumentJS
3.14.1
5.0.0 4.3.0 2.3.35
  • About
  • Guides
  • API Docs
  • Community
  • Contributing
  • Bitovi
    • Bitovi.com
    • Blog
    • Design
    • Development
    • Training
    • Open Source
    • About
    • Contact Us
  • About
  • Guides
  • API Docs
    • Observables
      • can-compute
      • can-define
      • can-define/list/list
      • can-define/map/map
      • can-define-stream
      • can-define-stream-kefir
      • can-event
      • can-event/async/async
      • can-event/batch/batch
      • can-event/lifecycle/lifecycle
      • can-kefir
      • can-list
      • can-map
      • can-map-backup
      • can-map-define
      • can-observation
      • can-observe
      • can-simple-map
      • can-simple-observable
      • can-stream
      • can-stream-kefir
    • Data Modeling
      • can-connect
      • can-connect-cloneable
      • can-connect-feathers
      • can-connect-ndjson
      • can-connect-signalr
      • can-fixture
      • can-fixture-socket
      • can-ndjson-stream
      • can-set
    • Views
      • can-component
      • can-ejs
      • can-element
      • can-react-component
      • can-stache
        • Pages
          • Magic Tag Types
          • Scope and Context
          • Expressions
          • Template Acquisition
          • Helpers
          • Live Binding
          • Whitespace Control
          • Sections
        • Methods
          • addHelper
          • addLiveHelper
          • from
          • registerConverter
          • registerHelper
          • registerPartial
          • registerSimpleHelper
          • safeString
        • Tags
          • {{expression}}
          • {{{expression}}}
          • {{#expression}}
          • {{/expression}}
          • {{^expression}}
          • {{>key}}
          • {{!expression}}
          • {{<partialName}}
          • {{else}}
        • Expressions
          • Bracket Expression
          • Call Expression
          • Hash Expression
          • Helper Expression
          • KeyLookup Expression
          • Literal Expression
        • Key Operators
          • @at
          • ~compute
          • ./current
          • ../parent
          • scope
          • %special
          • this
          • *variable
          • *self
          • key
        • Helpers
          • {{#if(expression)}}
          • {{#unless(expression)}}
          • {{#each(expression)}}
          • {{#with(expression)}}
          • {{log()}}
          • {{debugger()}}
          • {{#eq(expressions)}}
          • {{#is(expressions)}}
          • {{#switch(expression)}}
          • {{#case(expression)}}
          • {{#default()}}
          • {{joinBase(expressions)}}
        • Types
          • getterSetter
          • helper
          • helperOptions
          • renderer
          • sectionRenderer
          • simpleHelper
      • can-stache/helpers/route
      • can-stache-bindings
      • can-stache-converters
      • can-view-autorender
      • can-view-callbacks
      • can-view-href
      • can-view-import
      • can-view-live
      • can-view-model
      • can-view-nodelist
      • can-view-parser
      • can-view-scope
      • can-view-target
      • react-view-model
      • react-view-model/component
      • steal-stache
    • Routing
      • can-deparam
      • can-param
      • can-route
      • can-route-pushstate
    • JS Utilities
      • can-assign
      • can-define-lazy-value
      • can-globals
      • can-key-tree
      • can-make-map
      • can-parse-uri
      • can-string
      • can-string-to-any
      • can-util
      • can-zone
      • can-zone-storage
    • DOM Utilities
      • can-ajax
      • can-attribute-encoder
      • can-control
      • can-dom-events
      • can-event-dom-enter
      • can-event-dom-radiochange
      • can-jquery
    • Data Validation
      • can-define-validate-validatejs
      • can-validate
      • can-validate-interface
      • can-validate-legacy
      • can-validate-validatejs
    • Typed Data
      • can-cid
      • can-construct
      • can-construct-super
      • can-namespace
      • can-reflect
      • can-reflect-promise
      • can-types
    • Polyfills
      • can-symbol
      • can-vdom
    • Core
    • Infrastructure
      • can-global
      • can-test-helpers
    • Ecosystem
    • Legacy
  • Community
  • Contributing
  • GitHub
  • Twitter
  • Chat
  • Forum
  • News
Bitovi

{{<partialName}}

  • Edit on GitHub

Create an inline named partial within the current template.

{{<partialName}}BLOCK{{/partialName}}

Creates a reusable sub-template from BLOCK named partialName that can be rendered recursively or in the current scope using {{>partialName}}.

{{<addressTemplate}}
    <div>{{street}}, {{city}}</div>
{{/addressTemplate}}

<div>
    {{#with(business.address)}}
        {{>addressTemplate}}
    {{/with}}
</div>
<ul>
    {{#each(business.people)}}
        <li>
            {{fullName}}, {{birthday}}
            {{>addressTemplate address}}
        </li>
    {{/each}}
</ul>

Parameters

  1. partialName {String}:

    The name of the partial.

  2. BLOCK {sectionRenderer(context, helpers)}:

    a template to be captured and rendered later.

Use

Named partials are sub-templates in a larger template that aren’t rendered until referenced by the partial tag. They can be referenced any number of times with different contexts.

Given this data:

{
    business: {
        name: "Bitvoi",
        address: { street: "Hello", city: "World" }
    },
    people: [
        {
            fullName: "James Atherton",
            address: {
                street: "123 45th Street",
                city: "Moline"
            }
        },
        {
            fullName: "Someone Else",
            address: {
                street: "678 90th St",
                city: "Chicago"
            }
        }
    ]
}

This template:

{{<addressTemplate}}
    <div>{{street}}, {{city}}</div>
{{/addressTemplate}}

<div>
    {{#with(business.address)}}
        {{>addressTemplate}}
    {{/with}}
</div>
<ul>
    {{#each(business.people)}}
        <li>
            {{fullName}}
            {{>addressTemplate address}}
        </li>
    {{/each}}
</ul>

Would result in:

<div>
    <div>Hello, World</div>
</div>
<ul>
        <li>
            James Atherton
            <div>123 45th Street, Moline</div>
        </li>
        <li>
            Someone Else
            <div>678 90th St, Chicago</div>
        </li>
</ul>

Named partials can also have a template block that references its own name in a partial tag, which creates recursion. (So make sure you avoid infinite loops!)

Given this data:

{
    yayRecursion: {
        name: "Root",
        nodes: [
            {
                name: "Leaf #1 in Root",
                nodes: []
            },
            {
                name: "Branch under Root",
                nodes: [
                    {
                        name: "Leaf in Branch",
                        nodes: []
                    }
                ]
            },
            {
                name: "Leaf #2 in Root",
                nodes: []
            }
        ]
    }
}

This template:

{{<recursive}}
    <div>{{./name}} <b>Type:</b> {{#if(./nodes.length)}}Branch{{else}}Leaf{{/if}}</div>
    {{#each(./nodes)}}
        {{>recursive .}}
    {{/each}}
{{/recursive}}

{{>recursive yayRecursion}}

Would result in:

<div>Root <b>Type:</b> Branch</div>
<div>Leaf #1 in Root <b>Type:</b> Leaf</div>
<div>Branch under Root <b>Type:</b> Branch</div>
<div>Leaf in Branch <b>Type:</b> Leaf</div>
<div>Leaf #2 in Root <b>Type:</b> Leaf</div>

Too Much Recursion

When working with recursive named partials, be aware that by default, expressions will walk up the context chain if the property is not found in the current context.

So if your data and template looks like this:

Given this data:

{
    yayRecursion: {
        name: "Root",
        nodes: [
            {
                name: "Branch #1 in Root",
                nodes: [
                    {
                        name: "Problem Child",
                        nodes: undefined
                    }
                ]
            }
        ]
    }
}

This template:

{{<recursive}}
    <div>{{name}} <b>Type:</b> {{#if(nodes.length)}}Branch{{else}}Leaf{{/if}}</div>
    {{#each(nodes)}}
        {{>recursive}}
    {{/each}}
{{/recursive}}

{{>recursive yayRecursion}}

Will recurse on nodes and your output will be something like this:

<div>Root <b>Type:</b> Branch</div>
<div>Branch #1 in Root <b>Type:</b> Leaf</div>
<div>Problem Child <b>Type:</b> Branch</div>
<div>Problem Child <b>Type:</b> Branch</div>
<div>Problem Child <b>Type:</b> Branch</div>
<div>Problem Child <b>Type:</b> Branch</div>
...
<div>Problem Child <b>Type:</b> Branch</div>
(hangs from too much recursion)

This is because when it’s rendering that named partial with “Problem Child” as the context, the template sees nodes here: {{#each(nodes)}}, then it checks the current context (Problem Child), doesn’t find anything called nodes, then moves up the scope to its parent context to check for nodes. Since nodes is on the parent (and contains the Problem Child), it uses that for the #each() and you’re stuck in infinite recursion.

To avoid that, it’s best practice to always be specific about the context for your expressions within a named partial:

{{<recursive}}
    <div>{{./name}} <b>Type:</b> {{#if(./nodes.length)}}Branch{{else}}Leaf{{/if}}</div>
    {{#each(./nodes)}}
        {{>recursive .}}
    {{/each}}
{{/recursive}}

{{>recursive yayRecursion}}

which prevents the default behavior for expressions to look up the context chain.

CanJS is part of DoneJS. Created and maintained by the core DoneJS team and Bitovi. Currently 3.14.1.

On this page

Get help

  • Chat with us
  • File an issue
  • Ask questions
  • Read latest news