meteor dynamic template data context - meteor

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.

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.

Importing my methods so that AutoForm can see them

I don't understand how to import my methods so that AutoForm can see them. Based on the 1.3 best practices, all inserts/updates/deletes should be blocked on the client, and we should use methods instead. These should be imported on a page-by-page basis on the client.
I tried removing the quotes around the meteormethod attribute, and importing the Method in the template's JS file, but this returns an error method.js:11 Uncaught Error: When form type is "method", you must also provide a "meteormethod" attribute.
What's the best practice for this? How do I tell AutoForm where to find my method?
I solved my own problem. Don't import anything, just reference the internal Meteor method name in AutoForm's meteormethod attribute.
For example (if you're using ValidatedMethod):
export const insertProject = new ValidatedMethod({
name: 'projects.insert',
validate: Projects.schema.validator(),
run(fields) {
Projects.insert(fields);
}
});
You'd then use:
{{> quickForm collection=projects id="insertProjectForm" type="method" meteormethod="projects.insert"}}
(note the meteormethod attribute is the same as the name attribute of the ValidatedMethod)
Ref: https://themeteorchef.com/snippets/using-validated-methods/

Use a variable to pick which partial to use

I'm looking to load a partial based on a variable that is in the front matter data of the content page that i have. I've been able to get handlebars to pass back the correct variable name from in side the page but it will not then process the resulting string as a request to a partial:
<div class="sub-column">{{> (rhs1) }}</div>
this then just outputs the content of the variable rather than then going to find the partial it is referring to. I have also tried is using {{{ }}} but this has not helped.
Is this possible or am I going about this the wrong way?
It seems to me this is your issue ...
From the documentation available here : http://handlebarsjs.com/partials.html
Subexpressions do not resolve variables so whichPartial must be a function. If a simple variable has the partial name, it's possible to resolve it via the lookup helper.
{{> (lookup . 'myVariable') }}
I had to use a helper function to return the partial:
fs.readFileSync('src/partials/'+content+'.html', 'utf8');
this then allowed the system to recognise that we wanted to point to the partial.

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