aldeed:template-extension

v3.3.0Published 9 years ago

This package has not had recent updates. Please investigate it's current state before committing to using it in your project.

Build Status

template-extension

A smart package for Meteor that allows you to:

  • iterate over all defined templates easily.
  • attach multiple created/rendered/destroyed hooks to a template.
  • attach a created/rendered/destroyed hook to all templates.
  • override a template but keep its helpers and events.
  • inherit the helpers from another template.
  • inherit the events from another template.
  • extend abstract templates and overwrite their events/helpers.
  • use template.parent(numLevels, includeBlockHelpers) to access a parent template instance.
  • use template.get(fieldName) to access the first field named fieldName in the current or ancestor template instances.
  • pass a function to Template.parentData(fun) to get the first data context which passes the test.

Prerequisites

Requires Meteor 1.0+

Installation

$ meteor add aldeed:template-extension

Template.forEach(callback)

Call callback once for each defined template. Generally, you'll want to call this in a Meteor.startup function or sometime after all templates have been loaded.

Template.onCreated / Template.onRendered / Template.onDestroyed

Run a function whenever any template is created/rendered/destroyed.

1Template.onRendered(function () {
2  // Initialize all datepicker inputs whenever any template is rendered
3  this.$('.datepicker').datepicker();
4});

hooks(options)

Use this instead of setting created/rendered/destroyed property directly. You can call it multiple times to attach multiple hooks to the same template.

1Template.foo.hooks({
2  created: function () {
3    console.log("foo created");
4  },
5  rendered: function () {
6    console.log("foo rendered");
7  },
8  destroyed: function () {
9    console.log("foo destroyed");
10  }
11});

replaces(templateName)

html

1<body>
2  {{> foo}}
3</body>
4
5<template name="foo">
6  {{bar}}
7  <button type="button">Click</button>
8</template>
9
10<template name="foo2">
11  {{bar}} 2
12  <button type="button">Click 2</button>
13</template>

client.js

1Template.foo.bar = function () {
2  return "TEST";
3};
4
5Template.foo.events({
6  'click button': function (event, template) {
7    console.log("foo button clicked");
8  }
9});
10
11Template.foo2.replaces("foo");

Whenever {{> foo}} is used, the contents of the foo2 template will be shown instead. The bar helper defined on "foo" will be used to resolve {{bar}}. Clicking the button will still fire the event defined on "foo".

This is useful when a package you are using defines a template for something and you'd like to adjust some things in that template for your app.

inheritsHelpersFrom(templateName) and inheritsEventsFrom(templateName)

html

1<body>
2  {{> foo}}
3  {{> foo2}}
4</body>
5
6<template name="foo">
7  {{bar}}
8  <button type="button">Click</button>
9</template>
10
11<template name="foo2">
12  {{bar}} 2
13  <button type="button">Click 2</button>
14</template>

client.js

1Template.foo.bar = function () {
2  return "TEST";
3};
4
5Template.foo.events({
6  'click button': function (event, template) {
7    console.log("foo button clicked");
8  }
9});
10
11Template.foo2.inheritsHelpersFrom("foo");
12Template.foo2.inheritsEventsFrom("foo");

In this example, both templates are rendered. Both use the bar helper defined on "foo" to resolve {{bar}}. Both fire the click event defined on "foo".

copyAs(newTemplateName)

html

1<body>
2  {{> foo}}
3  {{> bar}}
4</body>
5
6<template name="abstract_foo">
7{{#each images}}
8   <img src="{{src}}" alt="{{title}}" />
9{{/each}}
10</template>

client.js

1Template.abstract_foo.helpers({
2    images: function () {
3        return [];
4    }
5});
6
7Template.abstract_foo.copyAs('foo');
8Template.abstract_foo.copyAs('bar');
9
10Template.foo.helpers({
11    images: function () {
12        return Meteor.call('getFooImages');
13    }
14});
15
16Template.bar.helpers({
17    images: function () {
18        return Meteor.call('getBarImages');
19    }
20});

In this example, we defined "foo" and "bar" templates that get their HTML markup, events, and helpers from a base template, abstract_foo. We then override the images helper for "foo" and "bar" to provide template-specific images provided by different Meteor methods.

template.parent(numLevels, includeBlockHelpers)

On template instances you can now use parent(numLevels) method to access a parent template instance. numLevels is the number of levels beyond the current template instance to look. Defaults to 1. By default block helper template instances are skipped, but if includeBlockHelpers is set to true, they are not.

template.get(fieldName)

To not have to hard-code the number of levels when accessing parent template instances you can use get(fieldName) method which returns the value of the first field named fieldName in the current or ancestor template instances, traversed in the hierarchical order. It traverses block helper template instances as well. This pattern makes it easier to refactor templates without having to worry about changes to number of levels.

Template.parentData(fun)

Template.parentData now accepts a function which will be used to test each data context when traversing them in the hierarchical order, returning the first data context for which the test function returns true. This is useful so that you do not have to hard-code the number of levels when accessing parent data contexts, but you can use a more logic-oriented approach. For example, search for the first data context which contains a given field. Or:

1var data = Template.parentData(function (data) {return data instanceof MyDocument;});

Contributors