Say I have the following html.
<template name="Layout">
<div>{{name}}</div>
{{> yield}}
</template>
<template name="Home">
<div>Home Page</div>
</template>
However, data is now passed to Layout. How do I pass data in my home.js file to Layout? (In this case, I want to pass a name to {{name}})
you can use paths in data to refer to called data as in {{../name }}
also Template.parentData([numLevels])
http://docs.meteor.com/#/full/template_parentdata
The most typical way you share data between your .js files and your templates is via 'helpers'. You can create a simple helper to return the data to your Layout template.
In your JS file, put this anywhere:
Template.Layout.helpers({
name: function() {
return myVar;
}
})
If you use something like Iron Router, you can have a more 'global' data context for the route (page) you are on. When you are on a 'route' you can simply do this.myVar if its in the route data context.
Hope this helps.
Related
I am using meteor 1.4 for building a real time task assignment app.
I am stuck at a point when i want to include a template passing in an argument the template helper of that template to run.
Now when i pass the argument, it is passed as a string and i want to call that template helper. But i cannot find any way in spacebars to call a template helper when i have the helper name available as a context variable of string type.
Please tell whether it is possible and if yes, then how ??
Thanks in advance
Edit 1 - For ex.
<template name="parent">
{{> children helperParameter="someHelper"}}
</template>
<template name="child">
{{> child2 value=helperParameter }}
</template>
<template name="innerchild">
{{value}}
</template>
So basically, I want to pass the value returned by someHelper to the template innerchild and i want to decide which helper (in this case someHelper) to run in child by passing the name of that helper to child template from parent template.
Now, i can not run that helper in child template where i have its name in parameter helperParameter as a string.
Try Template.dynamic.
<template name="layout">
{{> Template.dynamic template=template}}
<!-- This is equivalent to
{{> nameOfNeededTemplate}}
-->
</template>
Template.layout.helpers({
template: function() {
return 'nameOfNeededTemplate';
}
});
I switched to Flow Router and I have a problem. how can I access the parent template data? with Iron Router the data was coming from router and was available inside the template, so if I wanted to access a parent data Template.parentData() was working.
But in Flow Router the data is not coming from router, it comes from helpers and Template.parentData() doesn't have the data in it anymore!
<template name="myTemplate">
{{#if Template.subscriptionsReady}}
{{> showPost parentPost }}
{{> newPost }}
{{/if}}
</template>
Template.myTemplate.helpers({
parentPost: function(){ return Posts.findOne({...})}
});
Template.newPost.events({
'submit .js-new-post':function(event,template){
console.log(Template.parentData(1).parentPost);
}});
You need to pass that data through to the Template.
E.g. {{> newPost parentPost=mydatahere}}
See more here: http://guide.meteor.com/blaze.html#name-data-contexts
I'm new to both meteor and JS.
I created a meteor app like this:
cd /tmp/
meteor create hello
cd hello
In hello.html I wrote this
<body>
<h1>Welcome to Meteor!</h1>
{{> t1}}
{{> t2}}
</body>
Then I added these templates:
<template name='t1'>
<span id='t1'>hello</span>
</template>
<template name='t2'>
<span id='t2'>world</span>
</template>
Then I wrote syntax inside of hello.js to get text from the DOM:
Template.t1.onRendered( function() {
mytext = $('span#t1').html() });
According to the debugger-console in my browser,
the above syntax works okay.
The debugger tells me that mytext == 'hello'
Question: How to share the mytext value with other parts of my Meteor app?
As written, mytext is stuck inside my anonymous function.
For example how would I make this call work:
$('span#t2').html(mytext)
??
You'll want to reactively watch your variable. An easy out-of-the-box solution for this is to use the Session variable. You can do it pretty easily like so:
Template.t1.onRendered( function() {
Session.set('mytext', $('span#t1').html());
});
Then in your second template, define and reference helper that returns that variable:
<!--html-->
<template name='t2'>
<span id='t2'>{{getMyText}}</span>
</template>
//js
Template.t2.helpers({
getMyText: function() { return Session.get('mytext'); }
});
The Session variable is reactive, so when the first template renders and sets the value of Session.mytext, the helper's result will be invalidated and the second template will update.
I would like to insert a string that contains a link with a helper (or is there any better option to achieve this?) in meteor blaze.
So far blaze just gives back the link as normal text with the '' tags.
Does anyone have a good solution or workaround for this?
Here is a simple example to get you started :
<template name="parent">
{{> linkTemplate linkData}}
{{#each links}}
{{> linkTemplate}}
{{/each}}
</template>
<template name="linkTemplate">
{{title}}
</template>
Links=new Meteor.Collection(null);
Links.insert({
url:"https://www.google.com",
title:"Google"
});
Template.parent.helpers({
linkData:function(){
return {
url:"https://www.google.com",
title:"Google"
};
},
links:function(){
return Links.find();
}
});
If you want to render a string in a template that happens to contain a link, you would have to provide the HTML string as in
var string="A link to Google.";
Then you can use the triple bracket syntax {{{helperReturningHTMLString}}} and it will work as expected, but I don't think it's good practice unless you're working with something like a WYSIWYG editor.
Here's what I want, a custom block helper that can act like a template, monitoring for it's own events etc. The html would look like this:
{{#expandable}}
{{#if expanded}}
Content!!!
<div id="toggle-area"></div>
{{else}}
<div id="toggle-area"></div>
{{/if}}
{{/expandable}}
And here's some javascript I have put together. This would work if I just declared the above as a template, but I want it to apply to whatever input is given to that expandable block helper.
Template.expandableView.created = function() {
this.data._isExpanded = false;
this.data._isExpandedDep = new Deps.Dependency();
}
Template.expandableView.events({
'click .toggle-area': function(e, t) {
t.data._isExpanded = !t.data._isExpanded;
t.data._isExpandedDep.changed();
}
});
Template.expandableView.expanded = function() {
this._isExpandedDep.depend();
return this._isExpanded;
};
I know I can declare block helpers with syntax like this:
Handlebars.registerHelper('expandable', function() {
var contents = options.fn(this);
// boring block helper that unconditionally returns the content
return contents;
});
But that wouldn't have the template behavior.
Thanks in advance! This might not be really possible with the current Meteor implementation.
Update
The implementation given by HubertOG is super cool, but the expanded helper isn't accessible from within the content below:
<template name="expandableView">
{{expanded}} <!-- this works correctly -->
{{content}}
</template>
<!-- in an appropriate 'home' template -->
{{#expandable}}
{{expanded}} <!-- this doesn't work correctly. Expanded is undefined. -->
<button class="toggle-thing">Toggle</button>
{{#if expanded}}
Content is showing!
{{else}}
Nope....
{{/if}}
{{/expandable}}
In the actual block helper, expanded is undefined, since the real thing is a level up in the context. I tried things like {{../expanded}} and {{this.expanded}}, but to no avail.
Strangely, the event handler is correctly wired up.... it fires when I click that button, but the expanded helper is simply never called from within the content, so even console.log() calls are never fired.
Meteor's new Blaze template engine solves this problem quite nicely.
Here's an excerpt from the Blaze docs showing how they can be used.
Definition:
<template name="ifEven">
{{#if isEven value}}
{{> UI.contentBlock}}
{{else}}
{{> UI.elseBlock}}
{{/if}}
</template>
Template.ifEven.isEven = function (value) {
return (value % 2) === 0;
}
Usage:
{{#ifEven value=2}}
2 is even
{{else}}
2 is odd
{{/ifEven}}
You can achieve this by making a helper that returns a template, and passing the helper options as a data to that template.
First, make your helper template:
<template name="helperTemplate">
<div class="this-is-a-helper-box">
<p>I'm a helper!</p>
{{helperContents}}
</div>
</template>
This will work as a typical template, i.e. it can respond to events:
Template.helperTemplate.events({
'click .click-me': function(e, t) {
alert('CLICK!');
},
});
Finally, make a helper that will return this template.
Handlebars.registerHelper('blockHelper', function(options) {
return new Handlebars.SafeString(Template.helperTemplate({
helperContents: new Handlebars.SafeString(options.fn(this)),
}));
});
The helper options are passed as a helperContents param inside the template data. We used that param in the template to display the contents. Notice also that you need to wrap the returned HTML code in Handlebars.SafeString, both in the case of the template helper and its data.
Then you can use it just as intended:
<template name="example">
{{#blockHelper}}
Blah blah blah
<div class="click-me">CLICK</div>
{{/blockHelper}}
</template>