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

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.

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

meteor dynamic template data context

This is a very simple repo, feel free to clone it to test a solution or comment on the commit if its an easy change I'm missing. https://github.com/Falieson/meteor-blaze-examples/commit/8e94f7008cecf647bb23269d9b92cbae49e2398a
I started with meteor create, tested the blaze-components package, and am now figuring out how to use {{> Template.dynamic template=childTemplate data=this }}.
The "hello" counter doesn't pass the value for the reactive variable down to the template, I thought it'd be accessible from {{#with this}} or {{this.count}}
Similarly I would expect the "info" template to render each of the links.
Thank you for your assistance!
It looks at first like there's an error where containerTemplate is receiving counterData as a variable named data but I'm trying to access it using this. When I change containerTemplate.html 's call to render the childTemplate too {{> Template.dynamic template=childTemplate data=data}} the template doesn't render.
All the changes I made in this commit are chasing data context passing for the wrong reasons. I wasn't receiving helper data in the rendered template but I was getting an error in my console that I thought I could ignore because it wasn't causing any issues until trying to use Template.dynamic
modules-runtime.js?hash=8587d18…:231 Uncaught Error: Cannot find module 'meteor/templating'
at makeMissingError (modules-runtime.js?hash=8587d18…:231)
Removing import { Template } from 'meteor/templating'; from my main.js fixed the issue immediately.

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

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

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