Динамические части руля
Я загружаю шаблон со следующими данными:
"slides": [
{
"template": "video",
"data": {
"video": ""
}
},
{
"template": "image",
"data": {
"image": ""
}
}
]
в моем шаблоне я хочу перебрать эти слайды и на основе настроенного шаблона, я хочу загрузить частичный
{{#each slides}}
{{> resources_templates_overlay_video }}
{{/each}}
Как я могу сделать эту частичную загрузку динамически (на основе настроенного шаблона)?
Я использую require-handlebars-plugin:
https://github.com/SlexAxton/require-handlebars-plugin
С уважением,
Даан
Ответы
Ответ 1
Насколько я могу судить, hbs ожидает, что частичные данные будут известны во время компиляции, что до того, как вы передадите свои данные. Пусть это обойдется.
Во-первых, потяните ваши динамические частицы перед рендерингом, например:
// I required the main template here for simplicity, but it can be anywhere
var templates = ['hbs!resources/templates/maintemplate'], l = data.slides.length;
for (var i=0; i<l; i++ )
templates.push('hbs!resources/templates/overlay/'+data[i].template);
require(templates, function(template) {
var html = template(data);
});
И определите помощника, который будет действовать как динамический частичный
define(['Handlebars'], function (Handlebars) {
function dynamictemplate(template, context, opts) {
template = template.replace(/\//g, '_');
var f = Handlebars.partials[template];
if (!f) {
return "Partial not loaded";
}
return new Handlebars.SafeString(f(context));
}
Handlebars.registerHelper('dynamictemplate', dynamictemplate);
return dynamictemplate;
});
Наконец, измените свой основной шаблон, чтобы он выглядел как
{{#each slides}}
{{dynamictemplate this.template this.data}}
{{/each}}
Ответ 2
Когда Handlebars.partials[]
возвращает необработанную строку, это означает, что частичная часть не скомпилирована.
Я не уверен, но лучше всего предположить, что Handlebars компилирует частичное внутренне, когда компилирует шаблон, который включает в себя частичный. Поэтому, когда вы используете помощника для включения частичного, тогда Handlebars не распознает его, и он не будет скомпилирован.
Вы можете скомпилировать частичную информацию. Не забудьте зарегистрировать скомпилированный фрагмент, или вы закончите компиляцию каждый раз, когда требуется частичное, что ухудшает производительность. Что-то вроде этого должно работать.
var template = Handlebars.partials['templatename'],
fnTemplate = null;
if (typeof template === 'function') {
fnTemplate = template;
} else {
// Compile the partial
fnTemplate = Handlebars.compile(partial);
// Register the compiled partial
Handlebars.registerPartial('templatename', fnTemplate);
}
return fnTemplate(context);
Ответ 3
Я нашел приведенные выше ответы немного трудными для понимания - они пропускают глобальные переменные, имеют одиночные переменные символов и некоторые странные имена. Итак, вот мой собственный ответ, для моей (и вашей) справки:
Динамическое частичное использование с использованием "hbs", express.js default handlebars:
Я использовал это, чтобы сделать простой блог, создав (article-name).md
в /blog/(article-name)
, создав динамическую частичную:
// Create handlebars partials for each blog item
fs.readdirSync('blog').forEach(function(blogItem){
var slug = blogItem.replace('.md','')
var fileContents = fs.readFileSync('blog/'+blogItem, 'utf8')
var html = marked(fileContents)
var compiledTemplate = hbs.compile(html);
hbs.registerPartial(slug, compiledTemplate);
})
// Create 'showBlogItem' helper that acts as a dynamic partial
hbs.registerHelper('showBlogItem', function(slug, context, opts) {
var loadedPartial = hbs.handlebars.partials[slug];
return new hbs.handlebars.SafeString(loadedPartial(context));
});
Здесь маршрут. Это 404s, если частичное не существует, потому что блог не существует.
router.get('/blog/:slug', function(req, res){
var slug = req.param("slug")
var loadedPartial = hbs.handlebars.partials[slug];
if ( ! loadedPartial ) {
return res.status(404).json({ error: 'Article not found' })
}
res.render('blog', {
slug: slug
});
})
/views/blog.hbs
выглядит следующим образом:
<div class="blog">
{{ showBlogItem slug }}
</div>