Files
meteor/docs/client/basic/sections/templates.md
2014-10-24 18:16:06 -04:00

8.5 KiB

{{#template name="basicTemplates"}}

Templates

In Meteor, you define your views in templates. A template is a snippet of HTML that can also include special pieces of code to include data and change which parts of the page are displayed.

Defining Templates in HTML

Templates are defined in .html files that can be located anywhere in your Meteor project folder except the server, public, and private directories.

Each .html file can contain any number of the following top-level elements: <head>, <body>, or <template>. Code in the <head> and <body> tags is appended to that section of the HTML page, and code inside <template> tags can be included using {{dstache}}> templateName}}, as shown in the example below. Templates can be included more than once — one of the main purposes of templates is to avoid writing the same HTML multiple times by hand.

<!-- add code to the <head> of the page -->
<head>
  <title>My website!</title>
</head>

<!-- add code to the <body> of the page -->
<body>
  <h1>Hello!</h1>
  {{dstache}}> welcomePage}}
</body>

<!-- define a template called welcomePage -->
<template name="welcomePage">
  <p>Welcome to my website!</p>
</template>

The {{dstache}} ... }} syntax is part of a language called "Spacebars" that Meteor uses to add functionality to HTML. As shown above, it lets you include templates in other parts of your page. Using Spacebars, you can also display data obtained from helpers. Helpers are written in JavaSript, and can be either simple values or functions.

{{> autoApiBox "Template#helpers"}}

Here's how you might define a helper called name for a template called nametag (in JavaScript):

Template.nametag.helpers({
  name: "Ben Bitdiddle"
});

And here is the nametag template itself (in HTML):

<!-- In an HTML file, display the value of the helper -->
<template name="nametag">
  <p>My name is {{dstache}}name}}.</p>
</template>

Spacebars also has a few other handy control structures that can be used to make your views more dynamic:

  • {{dstache}}#each data}} ... {{dstache}}/each}} - Iterate over the items in data and display the HTML inside the block for each one.
  • {{dstache}}#if data}} ... {{dstache}}else}} ... {{dstache}}/if}} - If data is true, display the first block; if it is false, display the second one.
  • {{dstache}}#with data}} ... {{dstache}}/with}} - Set the data context of the HTML inside, and display it.

Each nested #each or #with block has its own data context, which is an object whose properties can be used as helpers inside the block. For #with blocks, the data context is simply the value that appears after the #with and before the }} characters. For #each blocks, each element of the given array becomes the data context while the block is evaluated for that element.

For instance, if the people helper has the following value

Template.welcomePage.helpers({
  people: [{name: "Bob"}, {name: "Frank"}, {name: "Alice"}]
});

then you can display every person's name as a list of <p> tags:

{{dstache}}#each people}}
  <p>{{dstache}}name}}</p>
{{dstache}}/each}}

or use the "nametag" template from above instead of <p> tags:

{{dstache}}#each people}}
  <p>{{dstache}}> nametag}}</p>
{{dstache}}/each}}

Remember that helpers can be functions as well as simple values. For example, to show the logged in user's username, you might define a function-valued helper called username:

// in your JS file
Template.profilePage.helpers({
  username: function () {
    return Meteor.user() && Meteor.user().username;
  }
});

Now, each time use the username helper, the helper function will be called to determine the user's name:

// in your HTML
<template name="profilePage">
  <p>Profile page for {{username}}</p>
</template>

The helpers above have all been associated with specific templates, but you can also make a helper available in all templates by using Template.registerHelper.

You can find detailed documentation for Spacebars in the README on GitHub. Later in this documentation, the sections about Session, Tracker, Collections, and Accounts will talk more about how to add dynamic data to your templates.

{{> autoApiBox "Template#events"}}

The event map passed into Template.myTemplate.events has event descriptors as its keys and event handler functions as the values. Event handlers get two arguments: the event object and the template instance.

To attach event handlers to the following template

<template name="example">
  <button class="my-button">My button</button>
  <form>
    <input type="text" name="myInput" />
    <input type="submit" value="Submit Form" />
  </form>
</template>

you might call Template.example.events as follows:

Template.example.events({
  "click .my-button": function (event, template) {
    alert("My button was clicked!");
  },
  "submit form": function (event, template) {
    var inputValue = event.target.myInput.value;
    alert(inputValue);
  }
});

The first part of the key (before the first space) is the name of the event being captured. Pretty much any DOM event is supported. Some common ones are: click, mousedown, mouseup, mouseenter, mouseleave, keydown, keyup, keypress, focus, blur, and change.

The second part of the key (after the first space) is a selector that indicates which elements to listen to. This can be almost any selector supported by JQuery.

Whenever the indicated event happens on the selected element, the corresponding event handler function will be called with the relevant DOM event object and template instance. See the Event Maps section for details.

{{> autoApiBox "Template#rendered"}}

The function assigned to this property is called once for every instance of Template.myTemplate when it is inserted into the document for the first time.

This rendered callback can be used to integrate external libraries that aren't familiar with Meteor's automatic view rendering, and need to be initialized every time HTML is inserted into the page. Use the created and destroyed callbacks to perform initialization or clean-up on any objects.

For example, to use the HighlightJS library to apply code highlighting to all <pre> elements inside the codeSample template, you might assign the following function to Template.codeSample.rendered:

Template.codeSample.rendered = function () {
  hljs.highlightBlock(this.findAll('pre'));
};

In the callback function, this is bound to a template instance object that is unique to this inclusion of the template and remains across re-renderings. You can use methods like this.find and this.findAll to access DOM nodes in the template's rendered HTML.

Template instances

A template instance object represents a single inclusion of a template in the document. It can be used to access the DOM and it can be assigned properties that persist as the template is reactively updated.

Template instance objects can be found in several places:

  1. The value of this in the created, rendered, and destroyed template callbacks
  2. The second argument to event handlers
  3. As Template.instance() inside helpers

You can assign additional properties of your choice to the template instance to keep track of any state relevant to the template. For example, when using the Google Maps API you could attach the map object to the current template instance to be able to refer to it in helpers and event handlers. Use the created and destroyed callbacks to perform initialization or clean-up.

{{> autoApiBox "Blaze.TemplateInstance#findAll"}}

template.findAll returns an array of DOM elements matching selector. You can also use template.$, which works exactly like JQuery but only returns elements within template.

{{> autoApiBox "Blaze.TemplateInstance#find"}}

Get one DOM element matching selector, or null if there are no such elements. Like findAll, find only returns elements from inside the template.

{{/template}}