Как динамически загружать различные партиалы с помощью шаблонов рулей?

я загружаю шаблон со следующими данными:

"slides": [
    {
        "template": "video",
        "data": {
            "video": ""
        }
    },
    {
        "template": "image",
        "data": {
            "image": ""
        }
     }
]

в моем шаблоне я хочу зациклиться на этих слайдах и на основе настроенного шаблона я хочу загрузить частичный

{{#each slides}}
    {{> resources_templates_overlay_video }}
{{/each}}

Как я могу сделать эту частичную нагрузку динамически (на основе настроенного шаблона)?

Я использую требуется-руль-плагин

3 ответов


насколько я могу судить, 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}}

, когда Handlebars.partials[] возвращает необработанную строку, это означает, что частичный не компилируется.

Я не уверен, но мое лучшее предположение заключается в том, что руль компилирует частичное внутренне, когда он компилирует шаблон, который включает частичное. Поэтому, когда вы используете помощника для включения частичного, тогда руль не распознает его, и он не будет скомпилирован.

Вы можете compile частичная себе. Не забудьте зарегистрировать скомпилированный частичный, или вы закончите компиляцию каждый раз требуется частичное, что вредит производительности. Что-то вроде этого должно работать.

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);

Я нашел вышеуказанные ответы немного трудными для понимания - они пропускают глобалы, имеют одиночные символьные переменные и некоторые нечетные имена. Итак, вот мой собственный ответ для моей (и вашей) ссылки:

динамическое частичное использование' hbs', express.реализация рулей по умолчанию js:

я использовал это, чтобы сделать простой блог, что делает (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>