Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inject more data to handlebars during render #101

Closed
dominicbarnes opened this issue Jan 16, 2015 · 9 comments
Closed

Inject more data to handlebars during render #101

dominicbarnes opened this issue Jan 16, 2015 · 9 comments

Comments

@dominicbarnes
Copy link

It would be really helpful to add some more meta to options.data before rendering. In particular, I think that layout and view could be useful:

res.render("home", {
  layout: "default"
});
<script src="/public/layouts/{{@layout}}/index.js"></script>
<script src="/public/pages/{{@view}}/index.js"></script>
@ericf
Copy link
Owner

ericf commented Jan 16, 2015

Hmm…

So I do have some Express Handlebars-specific metadata that could potentially be useful, and it contains the layout name. But for the view name — I'm guessing your expecting view === "home" — rendering engines are only provided the view's file path.

Also, if we do something like this, I think this metadata should be namespaced on the data object so it doesn't clobber any user values, e.g. {{@expressHandlebars.view}} or something [better].

ericf added a commit that referenced this issue Feb 12, 2015
This upgrades to Handlebars 3.0 and makes backwards-incompatible
changes to the ExpressHandlebars API. Since Handlebars had a major
version bump, it seemed appropriate for this package to have a major
version bump as well, so I took the liberty of refactoring some things.

- Add `compilerOptions` config property which is passed along to
  `Handlebars.compile()` and `precompile()`.

- Expose ExpressHandlebars metadata to the `data` channel during
  render (#101). This metadata is accessibile via
  `@data.ExpressHandlebars.*`

- New "protected" hooks for AOP-ing template compilation and rendering,
  all of which can optionally return a Promise:

  - `_compileTemplate()`
  - `_precompileTemplate()`
  - `_renderTemplate()`

For most apps this will be a drop-in replacement to v1 of this package,
and using Handlebars 3.0 should be a drop-in replacement as well. That
said, here's the changes that potentially break back-compat:

- Removed using `prototype` props for default config values.

- Removed `handlebarsVersion` from instances and `getHandlebarsSemver`
  static function on the `ExpressHandlebars` constructor.

- Replaced undocumented `compileTemplate()` hook with the protected but
  supported `_compileTemplate()` and `_precompileTemplate()` hooks.
@ericf
Copy link
Owner

ericf commented Feb 12, 2015

@dominicbarnes I've added support for this in #105. Here is what I'm currently exposing on {{@ExpressHandlebars}}:

  • cache: Boolean, whether the cache option was true or false.
  • layout: String, the layout option value or defaultLayout config value.
  • data: Circular ref. to data.
  • helpers: The collection of helpers available during rendering.
  • partials: The collection of partials template functions available during rendering.
  • filePath: The file path of the template being rendered.

Are there any other things you were expecting to be available?

@dominicbarnes
Copy link
Author

That sounds great! I was just looking at this last night even, how funny.

I did discover that express.View does keep track of the name it was passed. (see https://github.com/strongloop/express/blob/master/lib/view.js#L43) Unfortunately, that's not available since we're overriding the context. (see https://github.com/ericf/express-handlebars/blob/master/lib/express-handlebars.js#L37)

The point is, it's not that far away and I think it's feasible to try and retrieve it.

@ericf
Copy link
Owner

ericf commented Feb 12, 2015

What are you thinking for the case where you have two subdirs in views/ and each have an foo.hbs template? Would you want to end up with something like: "about/foo" where the file exists at: "views/about/foo.hbs"?

@dominicbarnes
Copy link
Author

Yeah, that's what I was thinking. Whatever value that the user passes to res.render should be available to the template, in fact you could probably pass in both about/foo and /absolute/path/to/views/about/foo.hbs in case people want to do some sort of advanced resolution on their own.

@dominicbarnes
Copy link
Author

I haven't figured out exactly how you're assembling the data for the template, but I'm thinking something like:

var self = this;
this.engine = function (viewPath, options, callback) {
  options.view = this;
  self.renderView(viewPath, options, callback);
};

Where renderView needs to be aware of options.view and inject accordingly. :)

I know it's not nearly as clean as before, but it does accomplish the goal without too much extra code. Thoughts?

@ericf
Copy link
Owner

ericf commented Feb 13, 2015

So Express passes a settings object which contains views, and that's a string path to the views path. The problem is there won't be a way for me to create a string value that's equal to what the user passed to res.render() because all of these will be equivalent:

res.render('home');
res.render('home.hbs');
res.render('./views/home');
res.render('./views/home.hbs');

That said, what I'll do is something similar to how I process the partials and create their names; i.e., "about/foo".

@ericf
Copy link
Owner

ericf commented Feb 13, 2015

@dominicbarnes okay, added. Check out the commit linked above.

@dominicbarnes
Copy link
Author

Sounds good to me! I can't wait to see this merged, I'll be trying it out right away. :)

@ericf ericf closed this as completed in 47697a9 Mar 22, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants