Динамическая загрузка шаблонов в Meteor.js
Мне нужна возможность динамически загружать шаблоны без явного указания шаблона.
В качестве примера:
<template name="foo">
</template>
где 'foo' - это шаблон, я бы хотел, чтобы он динамически загружал его, вызывая некоторый метод:
Meteor.render(Meteor.loadTemplate('foo'));
Возможно ли это?
Ответы
Ответ 1
Meteor 0.9.x Новый API
Дэн Даскалеску отметил, что у Meteor теперь есть встроенные динамические шаблоны! Это хорошо, потому что вам не нужно включать дополнительный код, как показано в предыдущих версиях.
{{> Template.dynamic template=template [data=data] }}
Для Meteor 0.8.x Legacy
Динамический шаблон без данных: Boris Kotov обновленный Blaze (0.8.0) ответ на правильном пути (взято из последних документов), но он не работает как есть для меня. Я получил следующее:
{{> dynamicTemplate name=myDynName}}
<template name="dynamicTemplate">
{{#with chooseTemplate name}}
{{> template}}
{{/with}}
</template>
Template.dynamicTemplate.chooseTemplate = function (name) {
return { template: Template[name] };
};
Надеюсь, что есть более простое решение, но мне нужно было обернуть шаблон в JSON, как показано. Возможно, это поможет кому-то еще двигаться вперед.
Динамический шаблон с данными: если у вас есть и хотите, чтобы данные были динамическими, обязательно создайте вспомогательный метод, который может реагировать. Обязательно выполните Session.set() где-нибудь, чтобы увидеть эффект.
// Inside "myContainingTemplate"
{{> dynamicTemplateWithData name=myDynName data=myDataHelper}}
<template name="dynamicTemplateWithData">
{{#with chooseTemplate name}}
{{#with ../data}}
{{> ..}}
{{/with}}
{{/with}}
</template>
Template.dynamicTemplateWithData.chooseTemplate = function (name) {
return Template[name];
};
Template.myContainingTemplate.helpers({
myDataHelper: function () {
Session.get('myReactiveKey');
}
});
Ответ 2
Здесь, как динамически отображать шаблоны, с Meteor 0.9.4 - 1.0. Все остальные ответы были устаревшими на момент написания этой статьи.
Скажем, вы редактируете кучу записей или создаете новую и хотите отобразить либо шаблон update
, либо шаблон new
на основе некоторых переменных сеанса.
Есть два способа сделать это:
1) Это официально рекомендованный метод для Meteor 0.9.4 или новее - он использует Template.dynamic
:
<template name="records">
{{> Template.dynamic template=whichOne}}
</template>
<template name="recordUpdate">
...
</template>
<template name="recordNew">
...
</template>
Template.records.helpers({
whichOne: function () {
return Session.get('edit') ? 'recordUpdate' : 'recordNew'
// note that we return a string - per http://docs.meteor.com/#template_dynamic
}
});
2) Это работает в разных версиях Meteor, но официально не рекомендуется, поскольку неясно, что шаблон выбран динамически:
<template name="records">
{{> whichOne}}
</template>
{{! Note how "whichOne" is indistinguishable from a constant template name... }}
{{ ...like "recordUpdate" or "recordNew" below. }}
<template name="recordUpdate">
...
</template>
<template name="recordNew">
...
</template>
Template.records.helpers({
whichOne: function () {
return Session.get('edit') ? Template.recordUpdate : Template.recordNew
// note that we return a Template object, not a string
}
});
Чтобы передать контекст данных в шаблон, используйте:
{{> Template.dynamic template=whichOne data=myData}}
Ответ 3
Вы нашли Meteor.render, но то, что вам не хватает, это загрузка шаблона.
В документах упоминается, что вы можете вызвать Template.foo(), чтобы вернуть HTML для шаблона.
http://docs.meteor.com/#template_call
Объединяя это, вы получаете доступ к шаблону foo или любому другому, используя доступ к скобкам так:
var templateName = "foo";
var fragment = Meteor.render( function() {
return Template[ templateName ](); // this calls the template and returns the HTML.
});
Затем фрагмент - это ваш реактивный фрагмент, чтобы ваш шаблон мог продолжать получать текущие обновления. Теперь вашему фрагменту нужно разместить на веб-странице (я использую jQuery, поэтому этот пример тоже):
$("#htmlnode").html( fragment );
$( "# htmlnode" ) - это всего лишь node в вашей DOM, где вы хотите, чтобы созданный шаблон. И теперь у вас есть отображаемый контент на вашей веб-странице.
Ответ 4
Я просто делаю это так, не требуется jQuery:
EDITED
Template.mainContent.showContentFromRouter = function() {
return Template[Meteor.Router.page()]();
};
В этом случае я использую Meteor Router и возвращаю любой шаблон, который я выбираю (из Router), но вы могли бы просто сделать это:
Template.mainContent.showDynamicContent = function() {
return Template['someTemplateYouveDefined']();
};
Ответ 5
Обновление для пламени:
https://github.com/meteor/meteor/wiki/Using-Blaze#templatefoo-is-not-a-function-and-does-not-return-a-string
Динамически визуализировать шаблон с заданным контекстом данных
Старый:
{{dynamicTemplate name="templateName" data=dataContext}}
Template.foo.dynamicTemplate = function (opts) {
return Template[opts.name](opts.data);
};
Новое: (Примечательно, что в Blaze аргументы ключевого слова для включения или блочные помощники объединяются в один объект, который становится новым контекстом данных)
{{> dynamicTemplate name="templateName" data=dataContext}}
<template name="dynamicTemplate">
{{#with chooseTemplate name}}
{{#with ../data}} {{! original 'data' argument to DynamicTemplate}}
{{> ..}} {{! return value from chooseTemplate(name) }}
{{/with}}
{{/with}}
</template>
Template.dynamicTemplate.chooseTemplate = function (name) {
return Template[name];
}
Кстати, я на самом деле не играл с этим, но это то, что я взял из новых документов blaze. Поэтому я думаю, что это должен быть способ сделать это;)
Ответ 6
Meteor 0.8.x Legacy
Используя ответ Joc в качестве руководства,
Я добился аналогичного использования http://docs.meteor.com/#template_call, но вместо этого использовал помощник, как это было предложено документами:
При вызове внутри вспомогательного элемента шаблона, тела Meteor.render или других параметров, где генерируется реактивный HTML, полученный HTML-код аннотируется так, что он отображает как реактивные элементы DOM
Мой client.js выглядит примерно так:
Template.myPageTemplate.helpers({
dynamicTemplate: function() {
// conditional logic can be added here to determine which template to render
return Template.myDynamicTemplate();
}
});
и мой html выглядит так:
<template name="myPageTemplate">
<h1>My Template</h1>
{{{dynamicTemplate}}}
</template>
<template name="myDynamicTemplate">
<h1>My Dynamic Template</h1>
</template>
Ответ 7
Из https://github.com/meteor/meteor/wiki/Using-Blaze
{{> post}}
Template.foo.helpers({
post: function () {
return Template[this.postName];
}
});
Вложения шаблонов теперь ищут пространство имен помощников и данные для объектов шаблона, поэтому легко программно выбирать, какой шаблон использовать. Это мощная функция и позволит шаблонам, например, назначать один шаблон в качестве помощника другого, чтобы его можно было переопределить.
Ответ 8
Основанный на ответе на холм, это самый простой способ:
Template.main.template = function() {
if (some_condition) {
return Template.A();
} else {
return Template.B();
}
};
С соответствующим .html
<body>
{{> main}}
</body>
<template name="main">
{{{template}}}
</template>
<template name="A">
<h1>Template A</h1>
</template>
<template name="B">
<h1>Template B</h1>
</template>
Edit
Не работает в Meteor 0.8.0
Ответ 9
для меня самым простым способом было просто создать функцию get_dynamic_template, поэтому что-то вроде:
var a= get_dynamic_template(template_name,data);
который возвращает то, что может отображаться как нормальная переменная {{a}}
Код для этой функции довольно прост:
var get_dynamic_template = function(template_name,data)
{
return function(){
return new Handlebars.SafeString(
UI.toHTML(
Template[template_name].extend({data: function () { return data; }}))
);
};
}
Ответ 10
Это позволит обрабатывать динамические шаблоны как с данными, так и без них:
(требуется Blaze/Meteor 0.8)
{{> dynamicTemplate name=templateName}}
<template name="dynamicTemplate">
{{#with chooseTemplate name }}
{{#if ../data}}
{{#with ../data }}
{{> .. }}
{{/with}}
{{else}}
{{> this}}
{{/if}}
{{/with}}
<template name="dynamicTemplate">
шаблон javascript:
Template.dynamicTemplate.chooseTemplate = function (name) {
return Template[name];
};