pcardune / handlebars-loader

A handlebars template loader for webpack
556 stars 169 forks source link

Dynamic partials #81

Open martijnvermaat opened 8 years ago

martijnvermaat commented 8 years ago

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.

eddiemoore commented 8 years ago

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.

martijnvermaat commented 8 years ago

I used inline partials as a workaround for now.

derekwheee commented 7 years ago

Are there any plans to support dynamic partials? Either with

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

pcardune commented 7 years ago

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 notifications@github.com 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 .

Tsouef commented 7 years ago

Someone found a solution for that ?

gko commented 7 years ago

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

spike008t commented 6 years ago

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';
MelanieMenard commented 6 years ago

@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!

spike008t commented 6 years ago

@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';
MelanieMenard commented 6 years ago

@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);
spike008t commented 6 years ago

@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 commented 6 years ago

@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.