Guidon dynamique partiel

Je charge un modèle avec les données suivantes:

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

Dans mon modèle, je souhaite boucler ces diapositives et, en fonction du modèle configuré, je veux charger une partie

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

Comment puis-je effectuer cette charge partielle de manière dynamique (en fonction du modèle configuré)?

J'utilise le plugin require-handlebars: https://github.com/SlexAxton/require-handlebars-plugin

sincères amitiés,

Daan

Pour autant que je le sache, hbs s'attend à ce que les partiels soient connus au moment de la compilation, ce qui est bien avant que vous ne passiez vos données. Examinons cela.

Tout d'abord, tirez vos partiels dynamiques avant le rendu, quelque chose comme:

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

Et définissez un assistant qui agira comme une partie partielle dynamique

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

Enfin, modifiez votre modèle principal pour ressembler

 {{#each slides}} {{dynamictemplate this.template this.data}} {{/each}} 

Lorsque Handlebars.partials[] renvoie une chaîne brute, cela signifie que la partie n'est pas compilée.

Je ne suis pas sûr, mais ma meilleure estimation est que Handlebars compile le partiellement interne lorsqu'il compile le modèle qui inclut le partiel. Donc, lorsque vous utilisez un assistant pour inclure une partie, les Guidons ne le reconnaissent pas et il ne sera pas compilé.

Vous pouvez compiler la partie vous-même. N'oubliez pas d'enregistrer la partie compilée ou vous finissez par compiler chaque fois que la partie est nécessaire, ce qui nuit aux performances. Une telle chose devrait fonctionner.

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

J'ai trouvé les réponses ci-dessus un peu difficiles à comprendre – elles fuient des globals, ont des variables de caractères uniques et certaines noms étranges. Voici donc ma propre réponse, pour ma (et votre) référence:

Une implémentation partielle dynamique utilisant 'hbs', implantation de guidons par défaut express.js :

J'ai utilisé cela pour créer une simple création de blog (article-name).md dans /blog/(article-name) , en créant une partie partielle dynamique:

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

Voici la route. Il est 404 si le partiel n'existe pas, car le blog n'existe pas.

 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 ressemble à:

 <div class="blog"> {{ showBlogItem slug }} </div>