Template7 示例


{{#each}}...{{else}}...{{/each}}

{{#each}} is a block expression, that iterates through items of passed Array or through properties of passed Object.

The following additional variables are available inside of this helper:

  • @index - index number of the item. For arrays only

  • @first - equal to true for the first item in array. For arrays only

  • @last - equal to true for the last item in array. For arrays only

  • @key - name of current object property. For objects only

Iterate through Array items

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Template7 实例教程
        </title>
    </head>
    <body>
        <div class="views">
            <div class="view view-main">
                <div class="pages">
                    <script id="homeTemplate" type="text/template7">
                        <div data-page="home" class="page">
                            <div class="page-content">
                                <div class="content-block">
                                    <p>Here are the list of people i know:</p>
                                    <ul>
                                      {{#each people}}
                                      <li>{{firstName}} {{lastName}}</li>
                                      {{/each}}    
                                    </ul>          
                                </div>
                            </div>
                        </div>    
                    </script>
                </div>
            </div>
        </div>
        <script type="text/javascript" src="//ku.shouce.ren/libs/fk7/1.4.2/js/framework7.min.js">
        </script>
        <script>// 声明Dom7
            var $$ = Dom7;
            // 初始化 App
            var myApp = new Framework7({
                precompileTemplates: true
                });
            var mainView = myApp.addView('.view-main');
            // Now we may render our compiled template by passing required context
            var context = {
                  people : [
                    {
                      firstName: 'John',
                      lastName: 'Doe'
                    },
                    {
                      firstName: 'Mark',
                      lastName: 'Johnson'
                    },
                  ]
                }    ;
            mainView.router.load({
                template: Template7.templates.homeTemplate,
                context: context
            })
        </script>
    </body>
</html>

实例预览

<p>Here are the list of people i know:</p>
<ul>
    {{#each people}}
    <li>{{@index}}. {{this}}
    </li>
    {{/each}}    
</ul>
<script>
var context = {
people : ['John Doe', 'Mark Johnson']
}
</script>

实例预览

Iterate through Object properties

<p>Car properties:</p>
<ul>
    {{#each props}}
    <li>{{@key}}: {{this}}
    </li>
    {{/each}}
</ul>
<script>
    var context = {
        props: {
            power: '150 hp',
            speed: '200 km/h',
        }
    };
</script>

实例预览

{{else}} expression

<p>Car properties:</p>
<ul>
    {{#each props}}
    <li>{{@key}}: {{this}}</li>
    {{else}}
    <li>No properties</li>
    {{/each}}
</ul> 
<script>
    var context = {
        props: {
            power: '150 hp',
            speed: '200 km/h',
        }
    };
</script>

实例预览

{{#if}}...{{else}}...{{/if}}

{{#if}} helper renders content if passed context is not "false" (or "undefined" or "null" or "" or "0") , otherwise it renders inverse content that optionally could be passed to {{else}} expression inside of helper:

<a href="#" {{#if active}}class="active"{{/if}}>{{title}}</a>
<script>
    var context ={
        active: true,
        title: 'Link',
    };
</script>

实例预览

{{else}} expression

<p>Hello, my name is {{name}}.</p>
{{#if hobby}}
<p>I have hobby</p>
{{else}}
<p>I don't have hobby</p>
{{/if}}  
<script>
    var context ={
        name: 'John Doe',
        hobby: false
    };
</script>

 实例预览

{{#unless}}...{{else}}...{{/unless}}

{{#unless}} helper renders content if passed context is "false" (or "undefined" or "null" or "" or "0") , otherwise it renders inverse content that optionally could be passed to {{else}} expression inside of helper:

<a href="#" {{#unless active}}class="active"{{/unless}}>{{title}}</a>
<ul>
    {{#each props}}
    <li>{{@key}}: {{this}}
    </li>
    {{/each}}
</ul>
<script>
    var context={
        active: true,
        title: 'Link',
    };
</script>

实例预览

{{else}} expression

<p>Hello, my name is {{name}}.</p>
{{#unless hobby}}
<p>I have hobby</p>
{{else}}
<p>I don't have hobby</p>
{{/unless}}  
<ul>
    {{#each props}}
    <li>{{@key}}: {{this}}</li>
    {{/each}}
</ul>
<script>
    var context={
        name: 'John Doe',
        hobby: false
    };
</script>

实例预览

{{#with}}...{{/with}}

{{#with}} helper changes rendering context to the passed context:

{{#with props}}
<p>Car has {{power}} power and {{speed}} maximum speed</p>
{{/with}}
<script>
    var context={
        props: {
            power: '150 hp',
            speed: '200 km/h',
        }
    };
</script>

实例预览

{{#variableName}}...{{/variableName}}

If you pass a block expression with helper name that is in the expression context, then it will work like {{#each}} helper for this context if it is an Array, and will work like {{#with}} helper if it is an Object:

<ul>
    {{#people}}
    <li>{{name}} - {{age}} years old</li>
    {{/people}}
</ul>
<script>
    var context={
        people: [
            {
                name: 'John Doe',
                age: 18
            }
            ,
            {
                name: 'Mark Johnson',
                age: 21
            }
        ]  
    };
</script>

实例预览

{{#props}}
<p>Car has {{power}} power and {{speed}} maximum speed</p>
{{/props}}
<script>
    var context={
        props: {
            power: '150 hp',
            speed: '200 km/h',
        }
    };
</script>

实例预览

{{join delimiter=""}}

This plain helper will join Array items to single string with passed delimiter

<h3>"{{title}}" TV Show</h3>
<p>Was released in year {{year}}</p>
<p>Genres: {{join genres delimiter=", "}}</p>
<script>
    var context={
        title: 'Friends',
        year: 2001,
        genres: ['comedy', 'drama']
    };
</script>

实例预览

{{escape}}

This plain helper returns escaped HTML string. It escapes only the following characters: < > " &

<h1>{{title}}</h1>
<p>{{escape body}}</p>
<script>
    var context={
        title: 'Paragraphs',
        body: 'We need to use <p> tags to add paragraphs in HTML',
    };
</script>

实例预览

{{js "expression"}}

This inline helper allows to execute some simple JavaScript directly in template to modify/check context on the fly or for some JS calculations

<h3>{{title}}</h3>
<p>Price: ${{js "this.price * 1.2"}}</p>
<p>{{js "this.inStock ? 'In Stock' : 'Not in stock'"}}</p>
<script>
    var context={
        title: 'iPhone 6 Plus',
        price: 1000,
        inStock: true
    };
</script>

实例预览

{{#js_compare "expression"}}...{{/js_compare}}

Block helper for easier compares of context variables. It renders content if JavaScript expression is not "false" (or "undefined" or "null" or "" or "0") , otherwise it renders inverse content that optionally could be passed to {{else}} expression inside of helper

<h3>{{title}}</h3>
<p>Price: ${{price}</p>
<p>{{#js_compare "this.color === 'white' && this.memory > 16"}}Not in stock{{else}}In stock{{/js_compare}}</p>
<script>
    var context={
        title: 'iPhone 6 Plus',
        price: 1000,
        color: 'white',
        memory: 32
    };
</script>

实例预览

Using Custom Helpers

Template7 allows to register custom helpers with the following method:

Template7.registerHelper(name, helper)

  • name - string - helper name
  • helper - function - helper function to handle passed context

Helper function could accepts as many arguments as required, arguments could be context, strings and hash data.

Let's look how to register helper on example of simple {{#if}} helper:

Template7.registerHelper('if', function (condition, options) {
  // "this" in function context is equal to the expression execution context
  // "condition" argument contains passed context/condition
  /*
    @options contains object with the wollowing properties and methods:
    "hash" - contains passed hash object with parameters
    "fn" - method to pass helper block content further to compilier
    "inverse" - method to pass helper block inverse ({{else}}) content further to compilier
    "data" - contains additional expression data, like @index for arrays or @key for object
  */
 
  // First we need to check is the passed context is function
  if (typeof condition === 'function') condition = condition.call(this);
 
  // If context condition
  if (condition) {
    // We need to pass block content further to compilier with the same context and the same data:
    options.fn(this, options.data);
  }
  else {
    // We need to pass block inverse ({{else}}) content further to compilier with the same context and the same data:
    options.inverse(this, options.data);
  }
});

Or on example of plain {{join}} helper:

Template7.registerHelper('join', function (arr, options) {
  // First we need to check is the passed arr argument is function
  if (typeof arr === 'function') arr = arr.call(this);
 
  /* 
    Passed delimiter is in the options.hash object:
    console.log(options.hash) -> {delimiter: ', '}
  */
 
  // And return joined array
  return arr.join(options.hash.delimiter);
});

Or we can create helper to create Framework7's list-block link to work with this syntax:

{{link url title target="_blank"}}
Template7.registerHelper('link', function (url, title, options){
  var ret = '<li>' +
              '<a href="' + url + '" class="item-content item-link" target="' + options.hash.target + '">' +
                '<div class="item-inner">' +
                  '<div class="item-title">' + title + '</div>' +
                '</div>' +
              '</a>' +
            '</li>';
  return ret;
});
<div class="list-block">
  <ul>
    {{#each links}}
    {{link url title target="_blank"}}
    {{/each}}    
  </ul></div>
{
  links: [
    {
      url: 'http://google.com',
      title: 'Google'
    },
    {
      url: 'http://idangero.us',
      title: 'iDangero.us'
    },
  ]
}

输出

<div class="list-block">
  <ul>
    <li>
      <a href="http://google.com" target="_blank" class="item-link item-content">
        <div class="item-inner">
          <div class="item-title">Google</div>
        </div>
      </a>
    </li>
    <li>
      <a href="http://idangero.us" target="_blank" class="item-link item-content">
        <div class="item-inner">
          <div class="item-title">iDangero.us</div>
        </div>
      </a>
    </li>
  </ul>
</div>

Note, that all custom helpers should be registered before you compile templates with these helpers!

Remove Custom Helpers

Template7 allows to remove custom helpers with the following method:

Template7.unregisterHelper(name)

  • name - string - helper name

Global Context

Template7 also supports global context which is accessible from any context.

We can specify it in Template7.global property:

Template7.global = {
    os: 'iOS',
    browser: 'Chrome',
    username: 'johndoe',
    email: 'john@doe.com'
};

To access it in templates we need to use {{@global}} variable:

<p>Hello, {{@global.username}}. Your email is {{@global.email}}</p>

Access To Root Context

Sometimes we may need to access to initially passed root context in our templates. For this case we need to use {{@root}} variable. This is especially helpful when we are deep in context:

{
    persons: [
        {
            name: 'John',
            hobby: ['Cars', 'Food']
        },
        {
            name: 'Kyle',
            hobby: ['Travel', 'Puzzles']
        },
 
    ],
    showHobby: true
}
{{#each persons}}
    <h2>{{name}}</h2>
    <h3>Hobby:</h3>
    {{#if @root.showHobby}}
        <ul>
            {{#each hobby}}
                <li>{{this}}</li>
            {{/each}}
        </ul>
    {{/if}}
{{/each}}

Partials

Template7 allows to reuse template using through partials. Partials are normal usual Template7 templates that may be called by other templates.

We can register and unregister partials using the following methods:

Template7.registerPartial(name, template) - register partial

  • name - string - partial name
  • helper - string - partial template

Template7.unregisterPartial(name) - unregister partial

  • name - string - partial name

Then we can use our partials using special helper {{> "partialName"}}

Template:

<ul class="users">
    {{#each users}}
    {{> "user"}}
    {{/each}}
</ul>
<ul class="admins">
    {{#each admins}}
    {{> "user"}}
    {{/each}}
</ul>

Register partial:

Template7.registerPartial('user', '<li><h2>{{firstName}} {{lastName}}</h2><p>{{bio}}</p></li>')

Apply to the template this context:

{
    users: [
        {
            firstName: 'John',
            lastName: 'Doe',
            bio: 'Lorem ipsum dolor'
        },
        {
            firstName: 'Jane',
            lastName: 'Doe',
            bio: 'Donec sodales euismod augue'
        }
    ],
    admins: [
        {
            firstName: 'Mike',
            lastName: 'Doe',
            bio: 'Lorem ipsum dolor'
        },
        {
            firstName: 'Kate',
            lastName: 'Doe',
            bio: 'Donec sodales euismod augue'
        }
    ]
}

And we will get the following output:

<ul class="users">
    <li>
        <h2>John Doe</h2>
        <p>Lorem ipsum dolor</p>
    </li>
    <li>
        <h2>Jane Doe</h2>
        <p>Donec sodales euismod augue</p>
    </li>
</ul>
<ul class="admins">
    <li>
        <h2>Mike Doe</h2>
        <p>Lorem ipsum dolor</p>
    </li>
    <li>
        <h2>Kate Doe</h2>
        <p>Donec sodales euismod augue</p>
    </li>
</ul>

Recursive Partials

We can even use partials to make recursive templates, like nested comments:

// Simple template with just a partial
var template = '{{> "comments"}}'
 
// Register partial
Template7.registerPartial(
    'comments', 
    '<ul>' + 
        '{{#each comments}}' +
            '<li>' +
            '<h2>{{author}}</h2>' +
            '<p>{{text}}</p>' +
            '{{#if comments}}{{> "comments"}}{{/if}}' +
            '</li>' +
        '{{/each}}' +
    '</ul>'
);
 
// Compile template 
var compiledTemplate = Template7.compile(template);
 
// Render template 
var output = compiledTemplate({
    comments: [
        {
            author: 'John Doe',
            text: 'Lorem ipsum dolor',
            comments: [
                {
                    author: 'Mike Doe',
                    text: 'Aliquam erat volutpat'
                },
                {
                    author: 'Kate Doe',
                    text: 'Donec eget fringilla turpis'
                }
            ]
        },
        {
            author: 'Jane Doe',
            text: 'Donec sodales euismod augue'
        }
    ]
})

And the output will be:

<ul class="comments">
    <li>
        <h2>John Doe</h2>
        <p>Lorem ipsum dolor</p>
        <ul class="comments">
            <li>
                <h2>Mike Doe</h2>
                <p>Aliquam erat volutpat</p>
            </li>
            <li>
                <h2>Kate Doe</h2>
                <p>Donec eget fringilla turpis</p>
            </li>
        </ul>
    </li>
    <li>
        <h2>Jane Doe</h2>
        <p>Donec sodales euismod augue</p>
    </li>
</ul>

Performance Tips

Template7 is fast and you can make it even faster in your apps. The slowest part (but still very fast in T7) in compilation/rendering process is the compilation from string to pure JS function when you do Template7.compile(). So don't compile the same templates multiple times, one time will be enough:

// Begin of your app
 
// Compile templates once on app load/init
var searchTemplate = $('script#search-template').html();
var compiledSearchTemplate = Template7.compile(searchTemplate);
 
var listTemplate = $('script#list-template').html();
var compiledListTemplate = Template7.compile(listTemplate);
 
// That is all, now and further just execute compiled templates with required context
// Just execute compiled search template with required content:
var html = compiledSearchTemplate({/*...some data...*/});
 
// Do something with html...