handlebars-loader icon indicating copy to clipboard operation
handlebars-loader copied to clipboard

Dynamic partials

Open martijnvermaat opened this issue 9 years ago • 12 comments
trafficstars

Handlebars has support for dynamic partials, but I did not get them to work with handlebars-loader.

Pseudo-example:

main.handlebars

---
<p>The statement below should resolve the 'world' partial and show 'Hello, world!'.</p>
{{> (lookup . 'hello') }}

world.handlebars

---
<p>Hello, world!</p>

main.js

---
require('main.handlebars')({hello: 'world'});

In the Handlebars Compiler APIs it is hinted that implementing nameLookup (as is done by handlebars-loader) will not be enough for dynamic partials; overriding VM.resolvePartial may be required. That method can be found here, but I honestly have no idea how to go about this.

Handlebars using current handlebars-loader fails with The partial world could not be found.

martijnvermaat avatar Jan 27 '16 23:01 martijnvermaat

I'm facing the same issue here. Been converting our Backbone require.js app over to webpack and this seems to be the only part that is holding me back now.

eddiemoore avatar Feb 16 '16 05:02 eddiemoore

I used inline partials as a workaround for now.

martijnvermaat avatar Feb 16 '16 07:02 martijnvermaat

Are there any plans to support dynamic partials? Either with

{{> (whichPartial) }} or {{> (lookup . 'myVariable') }}

derekwheee avatar Oct 20 '16 19:10 derekwheee

Only if someone submits a pull request with unit tests! At the moment I only have time for doing code reviews and cutting new releases, so it's up to others if people want new features. On Thu, Oct 20, 2016 at 12:19 PM Derek Wheelden [email protected] wrote:

Are there any plans to support dynamic partials? Either with

{{> (whichPartial) }} or {{> (lookup . 'myVariable') }}

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/pcardune/handlebars-loader/issues/81#issuecomment-255201833, or mute the thread https://github.com/notifications/unsubscribe-auth/AAHnm5MF64bbl6o7d1kmHgPhq3KuBt0lks5q176sgaJpZM4HN5mH .

pcardune avatar Oct 25 '16 18:10 pcardune

Someone found a solution for that ?

Tsouef avatar Jan 12 '17 08:01 Tsouef

@Tsouef handlebars-template-loader seems to support them but there are also troubles with other stuff

gko avatar Jan 19 '17 13:01 gko

I've found a workaround, the main problem is dynamic partial is not registered on Handlebars.partials context.

So to support dynamic partial, you need to register the precompiled template as partial on the handlebars global scope on your app first before doing your stuff.


import Handlebars from 'handlebars';

import MyPartial from './_myPartial.handlebars'; // precompile partial
Handlebars.partials['myPartial'] = MyPartial;  // register it as partial

 // here template.handlebars can use dynamic partial with myPartial
import template from './template.handlebars';

spike008t avatar Feb 15 '18 11:02 spike008t

@spike008t

Hello, I'm porting a backbone app from grunt to webpack and tried your solution but Iget the following error:

./node_modules/handlebars/lib/index.js
Module not found: Error: Can't resolve 'fs' in '/PATH_TO_MY_APP/node_modules/handlebars/lib'
 @ ./node_modules/handlebars/lib/index.js 17:11-24
 @ ./app/js/views/header-view.js
 @ ./app/js/views/app-layout.js
 @ ./app/js/controllers/router-controller.js
 @ ./app/js/application.js
 @ ./app/js/init.js
 @ multi (webpack)-dev-server/client?http://localhost:8000 webpack/hot/dev-server ./app/js/init.js

Does anyone have a clue what the problem is?

Many thanks in advance!

MelanieMenard avatar Feb 19 '18 14:02 MelanieMenard

@MelanieMenard I forget to mention my webpack.config....

I do have that:

{
  resolve: {
    alias: : {
      'handlebars': 'handlebars/runtime.js'
    }
  }
}

Could you try to call at the top of your js file if you haven't the alias.

import Handlebars from 'handlebars/runtime.js';

spike008t avatar Feb 19 '18 16:02 spike008t

@spike008t

Ah thank you! I came to similar solution from looking at how they register partials in other handlebars loader (https://github.com/emaphp/handlebars-template-loader) and got it to work:

import Handlebars from 'handlebars/runtime.js';
// precompile partial
import MyPartial from 'HandlebarsTemplates/my-partial.hbs';
// Register partial
Handlebars.registerPartial('my-partial', MyPartial);

MelanieMenard avatar Feb 19 '18 16:02 MelanieMenard

@MelanieMenard

At the end of the documentation about precompilation: https://handlebarsjs.com/precompilation.html

We can see:

Handlebars.partials["test1"] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) {
  var helper;

  return "<div>whatever "
  + container.escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"name","hash":{},"data":data}) : helper)))
  + "</div>";
},"useData":true});

I think both works, but normally, registerPartial takes as 2nd argument a template as "string" instead of a function...

spike008t avatar Feb 19 '18 16:02 spike008t

@pcardune I think handlebars-loader could not really handle correctly dynamic partials, because webpack guide line explain clearly loader should be simple and determinist. So we could not really update handlebars environment inside the loader.. I suggest to update the doc & example to explain how to use dynamic partials by register the partials in handlebars object. I can send a PR with an example of how to manage it.

spike008t avatar Feb 20 '18 13:02 spike008t