In Spacebars, can you combine an inclusion argument with a data object? - meteor

This is something I've come across a few times. I'd like to do
{{> subtemplate item foo="bar"}}
So that the data context in subtemplate has all the item fields plus a foo field. Don't see any way to do this in the docs
https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md
I know I could make my own helper combine to use like this: {{> subtemplate combine item "foo" "bar"}}, but am hoping there's a better way.

Can you use dynamic template to pass in your data context?
{{> Template.dynamic template=template [data=data] }}
See http://docs.meteor.com/#/full/template_dynamic

Related

How to render partials/helpers *inside* a string variable?

Say I've got the following template/scenario:
{{partial-container container}}
{{{content.html}}}
{{#each content.partials}}
{{this}} // <-- here I'd like to render partials that users requested.
{{/each}}
Goals
[Done] I want to render a block of text, html-escaped, using the html property.
From the JSON, we also get a list of "partials" to render, but I can't figure out how to make this work.
Ideally, the syntax would be something like this:
{{partial-container container}}
{{{content.html}}}
{{#each content.partials}}
{{ > {{this}} }}
{{/each}}
But that throws a syntax error. Is there any way to interpret the contents of a variable as the name for a partial to render (and do so)?
I am assuming that your "list of partials" is an array of names matching with registered partials. Something like:
"partials": ["fooPartial", "barPartial", "fooPartial"]
The Handlebars documentation states that partials can be dynamically selected using a subexpression, but this subexpression must be a function that returns the partial name. This means that something as simple as {{> (this)}} will not work because our this is the string value of our partial name and not a function.
I see two ways of achieving our goal.
Option 1: Map the partial names to functions
If we have the ability to modify the data we are sending to our template, we could map the partial names into functions that return the name:
"partials": ["fooPartial", "barPartial", "fooPartial"].map(partialName => () => partialName)
These functions would allow us to dynamically insert our partials into our template with {{> (this)}}.
See this fiddle for an example.
Option 2: Use the lookup helper
If modifying our input data is not an option, we can use the Handlebars built-in lookup helper. The trick here is that, within our #each loop, we must step-up a context-level to get our partials array and then use the #index helper variable to get the partial name at the current index. The template would become:
{{#each content.partials}}
{{> (lookup ../content.partials #index)}}
{{/each}}
See this fiddle for an example.

How can I access the parameter of a Handlebars inline partial from inside a loop?

I'm working on a Handlebars project and trying to use an inline partial. I'm trying to access the key parameter from within a loop.
{{#*inline "myPartial"}}
<div class="actionOverlay">
{{#each (lookup items key) }}
<span class="{{classes}} key-{{key}}" title="{{title}}"></span>
{{/each}}
</div>
{{/inline}}
And then invoking this inline partial with {{> myPartial key="0R"}}. The variable items is an array of objects with classes and title as keys.
Unfortunately {{key}} renders as empty string, no doubt because there is no key key in the items objects. I've also tried {{#root.key}} and that doesn't work.
How can I access the partial's parameter from within the loop?
Please note that I'm not trying to use a partial from within a loop, but trying to use a loop in a partial and to access the partial's parameter from within the loop.

How can I use an expression with the context of the call location as a parameter in a partial?

For example in a handlebars template:
{{#each data }}
{{> partial parameter=somethingFromThisContext }}
{{/each}}
and then in my partial:
{{ somethingFromThisContext }}
{{ data }}
Neither of them work. If I use a string as a parameter instead of data, the string will display, but all the other expressions in the partial will no longer work.
I'm not sure if I've understood you correctly, but you seem to have misunderstood handlebars' partial behaviour.
Inside a partial your scope will not be accessible, so you won't have access to any parameters you have in the template where you call your partial.
To pass parameters you have to assign them in the partial call like you did:
{{> partial parameter=somethingFromThisContext }}. However you've renamed your somethingFromThisContext to parameter now. So it's accessible like so: {{parameter}}.
It's like doing something like this in any programming language:
paramter = somethingFromThisContext;
There is a pretty nice Documentation page here, which may guide you further.

Can you pass a dynamic variable into a Meteor blaze template?

I saw the response to this stackoverflow post: Is there a way to pass variables into templates in Meteor?
The post only shows how to pass in a static value into blaze template. See the following example - I'm trying to pass in user.username into the template cookieTemplate
<template name="userTemplate">
<p> Wellcome {{user.username}} </p>
{{#each user.profile.cookies}}
{{> cookieTemplate username={{user.username}} }}
{{/each}}
</template>
<template name="cookieTemplate">
{{username}} has cookie {{this.cookieName}}
</template>
I know that I could potentially do this with Session.set('username', blah), but I was wondering if I can pass a dynamic variable into template?
A simple solution to yours is just to pass the user object to the template
{{> cookieTemplate user=user }}
and use it inside the template as
{{user.username}}
or you write down some helper to create a data object with relevant attributes like:
Template.userTemplate.helpers({
get_user: function() {
return { username: Template.instance().user.username }
}
and then call the template with
{{> cookieTemplate user=get_user }}
and use the value by
{{user.username}}
I made something similar (helper function) as a MeteorPad to this thread
Access an object's property names in a Blaze template
Maybe it helps you
Cheers,
Tom
Yes you can and might already be doing so.
In general if you are getting your data through auto publish or pub-sub, the data is considered reactive. Every time there is an update on the collection in anyway this update will be pushed to the template.
For your case, if you got the data through currentUser or Meteor.user() it would be the same case.

How to pass an object from to a block helper back to the block in meteor blaze?

Before Meteor 0.8, that brought blaze, I was able to pass objects to a custom block helper content like this:
return options.fn(object)
Now that with blaze, block helpers require to return a template something like this.
return Template.someTemplate
How can I achieve the old behaviour. What I want to to is the following:
I use a blockhelper
{{#blockhelper argument="something"}}
{{somePartOfTheObject}}
{{/blockhelper}}
Then in the the blockhelper definition, I want to do some stuff based on the argument, that will return an object.
UI.registerhelper "blockhelper", () ->
object = getStuffFrom(this.argument)
return Template.someTemplate(object)
As needed by blaze I created a minimal template
<template name="someTemplate">
{{> UI.contentBlock}}
</template>
Now blaze does not allow to pass an object to this template, so it can be used within the block contents.
How can I get around this?
I know the meteor-way would be to get the object in the controller. But as I want to use this for a prototyping framework, I want to be able to create said object or objects directly from the blockhelper, so someone can pass argmuents that will get converted to objects.
The solution turns out to really simple.
If I have a helper:
UI.registerhelper "blockhelper", () ->
object = getStuffFrom(this.argument)
return Template.someTemplate
The variables and object of the helper are actually available in the template. So you simply do:
<template name="someTemplate">
{{> UI.contentBlock object}}
</template>

Resources