{"id":13776356,"url":"https://github.com/longshotlabs/meteor-template-extension","last_synced_at":"2026-03-05T00:37:50.902Z","repository":{"id":19307468,"uuid":"22545208","full_name":"longshotlabs/meteor-template-extension","owner":"longshotlabs","description":"A Meteor package: Replace already defined templates, inherit helpers and events from other templates","archived":false,"fork":false,"pushed_at":"2017-03-03T15:29:57.000Z","size":61,"stargazers_count":219,"open_issues_count":5,"forks_count":25,"subscribers_count":16,"default_branch":"master","last_synced_at":"2026-01-18T15:23:05.967Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://atmospherejs.com/aldeed/template-extension","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/longshotlabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-08-02T11:53:12.000Z","updated_at":"2025-01-02T20:15:45.000Z","dependencies_parsed_at":"2022-09-01T17:03:00.616Z","dependency_job_id":null,"html_url":"https://github.com/longshotlabs/meteor-template-extension","commit_stats":null,"previous_names":["aldeed/meteor-template-extension"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/longshotlabs/meteor-template-extension","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longshotlabs%2Fmeteor-template-extension","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longshotlabs%2Fmeteor-template-extension/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longshotlabs%2Fmeteor-template-extension/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longshotlabs%2Fmeteor-template-extension/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/longshotlabs","download_url":"https://codeload.github.com/longshotlabs/meteor-template-extension/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longshotlabs%2Fmeteor-template-extension/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30102501,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T23:59:36.199Z","status":"ssl_error","status_checked_at":"2026-03-04T23:56:48.556Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T18:00:23.751Z","updated_at":"2026-03-05T00:37:50.855Z","avatar_url":"https://github.com/longshotlabs.png","language":"JavaScript","funding_links":[],"categories":["Uncategorized","Packages"],"sub_categories":["Uncategorized"],"readme":"[![Build Status](https://travis-ci.org/aldeed/meteor-template-extension.svg)](https://travis-ci.org/aldeed/meteor-template-extension)\n\ntemplate-extension\n=========================\n\nA smart package for Meteor that allows you to:\n\n* iterate over all defined templates easily.\n* attach multiple created/rendered/destroyed hooks to a template.\n* attach a created/rendered/destroyed hook to all templates.\n* override a template but keep its helpers and events.\n* inherit the helpers from another template.\n* inherit the events from another template.\n* extend abstract templates and overwrite their events/helpers.\n* use `template.parent(numLevels, includeBlockHelpers)` to access a parent template instance.\n* use `template.get(propName)` to get the value of the first property named `propName` on the current or an ancestor template instance.\n* use `template.set(propName, value)` to set the value of the first property named `propName` on the current or an ancestor template instance.\n* pass a function to `Template.parentData(fun)` to get the first data context which passes the test.\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [Installation](#installation)\n- [Compatibility](#compatibility)\n- [Template.forEach(callback)](#templateforeachcallback)\n- [Template.forEachCurrentlyRenderedInstance(callback)](#templateforeachcurrentlyrenderedinstancecallback)\n- [Template.onCreated / Template.onRendered / Template.onDestroyed](#templateoncreated--templateonrendered--templateondestroyed)\n- [hooks(options)](#hooksoptions)\n- [replaces(templateName)](#replacestemplatename)\n- [inheritsHelpersFrom(templateName), inheritsEventsFrom(templateName), and inheritsHooksFrom(templateName)](#inheritshelpersfromtemplatename-inheritseventsfromtemplatename-and-inheritshooksfromtemplatename)\n- [clearEventMaps()](#cleareventmaps)\n- [copyAs(newTemplateName)](#copyasnewtemplatename)\n- [templateInstance.parent(numLevels, includeBlockHelpers)](#templateinstanceparentnumlevels-includeblockhelpers)\n- [templateInstance.parent(selector, includeBlockHelpers)](#templateinstanceparentselector-includeblockhelpers)\n- [templateInstance.get(fieldName)](#templateinstancegetfieldname)\n- [Template.parentData(fun)](#templateparentdatafun)\n- [Contributors](#contributors)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Installation\n\n```bash\n$ meteor add aldeed:template-extension\n```\n\n## Compatibility\n\n- Use a 3.x.x release with Meteor 1.0.x or Meteor 1.1.x\n- Use a 4.x.x release with Meteor 1.2+\n\n## Template.forEach(callback)\n\nCall `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.\n\n## Template.forEachCurrentlyRenderedInstance(callback)\n\nCall `callback` once for each template instance that is currently rendered.\n\n## Template.onCreated / Template.onRendered / Template.onDestroyed\n\nRun a function whenever *any* template is created/rendered/destroyed.\n\n```js\nTemplate.onRendered(function () {\n  // Initialize all datepicker inputs whenever any template is rendered\n  this.$('.datepicker').datepicker();\n});\n```\n\n## hooks(options)\n\nAn alternative syntax to `onCreated`, `onRendered`, and `onDestroyed`.\n\n```js\nTemplate.foo.hooks({\n  created() {\n    console.log(\"foo created\");\n  },\n  rendered() {\n    console.log(\"foo rendered\");\n  },\n  destroyed() {\n    console.log(\"foo destroyed\");\n  },\n});\n```\n\n## replaces(templateName)\n\n*html*\n\n```html\n\u003cbody\u003e\n  {{\u003e foo}}\n\u003c/body\u003e\n\n\u003ctemplate name=\"foo\"\u003e\n  {{bar}}\n  \u003cbutton type=\"button\"\u003eClick\u003c/button\u003e\n\u003c/template\u003e\n\n\u003ctemplate name=\"foo2\"\u003e\n  {{bar}} 2\n  \u003cbutton type=\"button\"\u003eClick 2\u003c/button\u003e\n\u003c/template\u003e\n```\n\n*client.js*\n\n```js\nTemplate.foo.helpers({\n  bar() {\n    return \"TEST\";\n  },\n});\n\nTemplate.foo.events({\n  'click button'(event, template) {\n    console.log(\"foo button clicked\");\n  },\n});\n\nTemplate.foo2.replaces(\"foo\");\n```\n\nWhenever `{{\u003e 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\".\n\nThis 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.\n\nNOTE: This simply swaps the render function. Helpers, callbacks, and events assigned to `foo2` will not fire when `{{\u003e foo}}` is used. Only the `foo` helpers, callbacks, and events are used.\n\n## inheritsHelpersFrom(templateName), inheritsEventsFrom(templateName), and inheritsHooksFrom(templateName)\n\n*html*\n\n```html\n\u003cbody\u003e\n  {{\u003e foo}}\n  {{\u003e foo2}}\n\u003c/body\u003e\n\n\u003ctemplate name=\"foo\"\u003e\n  {{bar}}\n  \u003cbutton type=\"button\"\u003eClick\u003c/button\u003e\n\u003c/template\u003e\n\n\u003ctemplate name=\"foo2\"\u003e\n  {{bar}} 2\n  \u003cbutton type=\"button\"\u003eClick 2\u003c/button\u003e\n\u003c/template\u003e\n```\n\n*client.js*\n\n```js\nTemplate.foo.helpers({\n  bar() {\n    return 'TEST';\n  },\n});\n\nTemplate.foo.events({\n  'click button'(event, template) {\n    console.log('foo button clicked');\n  },\n});\n\nTemplate.foo.onCreated(function onCreated() {\n  console.log('foo created');\n});\n\nTemplate.foo2.inheritsHelpersFrom('foo');\nTemplate.foo2.inheritsEventsFrom('foo');\nTemplate.foo2.inheritsHooksFrom('foo');\n```\n\nIn 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\". The \"foo2\" template will inherit the `foo.created` callback and log 'foo' to the console upon creation.\n\nAdditionally, these methods can be called with an array of template names: `Template.foo2.inheritsHooksFrom(['foo', 'bar', 'baz']);`\n\nBecause of the different ways in which helpers, events, and hooks are stored, the ability to override them is different. Helpers are stored internally as a hash, which means that if you inherit a \"name\" helper and then call `myTemplate.helpers({ name: ... })`, the new \"name\" helper will overwrite the old helper. By contrast, events and hooks are stored in arrays, which means that you cannot override them easily. You may be able to achieve what you want with `clearEventMaps()` or looping through the events or hooks to somehow remove those you don't want.\n\n## clearEventMaps()\n\nAfter `Template.foo.events({...})` has been called one or more times, you can remove all the added event handlers by calling `Template.foo.clearEventMaps()`\n\n## copyAs(newTemplateName)\n\n*html*\n\n```html\n\u003cbody\u003e\n  {{\u003e foo}}\n  {{\u003e bar}}\n\u003c/body\u003e\n\n\u003ctemplate name=\"abstract_foo\"\u003e\n{{#each images}}\n   \u003cimg src=\"{{src}}\" alt=\"{{title}}\" /\u003e\n{{/each}}\n\u003c/template\u003e\n```\n\n*client.js*\n\n```js\nTemplate.abstract_foo.helpers({\n  images() {\n    return [];\n  }\n});\n\nTemplate.abstract_foo.copyAs(['foo', 'bar']);\n\nTemplate.foo.helpers({\n  images() {\n    return Meteor.call('getFooImages');\n  }\n});\n\nTemplate.bar.helpers({\n  images() {\n    return Meteor.call('getBarImages');\n  }\n});\n```\n\nIn 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.template.copyAs can accept either single template name (in string form), or an array of template names as shown in the above example.\n\nCalling `copyAs` is the same as calling `inheritsHelpersFrom`, `inheritsEventsFrom`, and `inheritsHooksFrom` and also copying the render function.\n\nIf copyAs is invoked with a string, it returns the newly created template.\n\nIf copyAs is invoked with an array, it returns an array of newly created templates.\n\n## templateInstance.parent(numLevels, includeBlockHelpers)\n\nOn template instances you can now use `parent(numLevels)` method to access a parent template instance.\n`numLevels` is the number of levels beyond the current template instance to look. Defaults to 1.\nBy default block helper template instances are skipped, but if `includeBlockHelpers` is set to true,\nthey are not.\n\n## templateInstance.parent(selector, includeBlockHelpers)\n\nYou can also call `templateInstance.parent` with function as first argument. The function, known as selector, will be\npassed the current template being traversed. If it returns true, we return the template that is currently being traversed,\notherwise, we traverse further up. We traverse up until there are no more templates, in which case, we return null.\n\n## templateInstance.get(fieldName)\n\nTo not have to hard-code the number of levels when accessing parent template instances you can use\n`get(fieldName)` method which returns the value of the first property named `fieldName` on the current\nor ancestor template instances, traversed in the hierarchical order. It traverses block helper template\ninstances as well. This pattern makes it easier to refactor templates without having to worry about\nchanges to number of levels.\n\n## Template.parentData(fun)\n\n`Template.parentData` now accepts a function which will be used to test each data context when traversing\nthem in the hierarchical order, returning the first data context for which the test function returns `true`.\nThis is useful so that you do not have to hard-code the number of levels when accessing parent data contexts,\nbut you can use a more logic-oriented approach. For example, search for the first data context which contains\na given field. Or:\n\n```js\nvar data = Template.parentData(function (data) {return data instanceof MyDocument;});\n```\n\n## Contributing\n\nWhen submitting a pull request, please add tests for any new features and make sure that all existing tests still pass.\n\n```bash\n$ meteor test-packages ./\n```\n\n### Contributors\n\n* @aldeed\n* @grabbou\n* @mitar\n* @jgladch\n* @merlinpatt\n* @JoeyAndres\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flongshotlabs%2Fmeteor-template-extension","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flongshotlabs%2Fmeteor-template-extension","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flongshotlabs%2Fmeteor-template-extension/lists"}