Meteor set overall template context - javascript

In meteor I can set various template helpers like this:
Template.story.title = function () {
return "title";
};
<template name="story">
<h3>{{title}}</h3>
<p>{{description}}</p>
</template>
Which is great but, if I have a lot of variables I wouldn't want to set them individually, I want to pass the context to the main template.
How do I do that?
Template.story.data = function () {
return {title:"title", description:"desc"};
};
<template name="story">
<h3>{{title}}</h3>
<p>{{description}}</p>
</template>
That doesn't work. THanks

You can set the context of the template when you call it:
{{> story data}}
Template.outerTemplate.data = function() {
return {title:"title", description:"desc"};
}
Or you can just use {{#with}} to set the the template context on the fly:
{{#with data}}
{{title}}
{{/with}}

You are absolutely on the right way but missed to use your template variable the way you defined it. As Template.story.data is defined to return an object, you should use it like an object:
<template name="story">
<h3>{{data.title}}</h3>
<p>{{data.description}}</p>
</template>
Voilá. Of course every template variable can hold more than just a string.

Related

What is a true equivalent of `window.onload` for an iron router route in a Meteor.js app?

I have an iron route defined like this (pay attention to onAfterAction and initProfileComponent)
var initProfileComponent = function () {
var elements = document.querySelectorAll('.sliderComponent');
//... do stuff and decorate the elements
}
Router.route('newProfile', {
path: '/new-profile/:_id',
onAfterAction: function () {
initProfileComponent();
},
data: function () {
return {profile: Profile.findOne({_id: this.params._id})};
}
});
The function initProfileComponent wishes to find using document.querySelectorAll elements created by meteor/mustache publish mechanism, that is why is called in onAfterAction, but obviously it doesn't work, since, when it is called the elements are not yet rendered.
The templates are defined like this :
<template name="newProfile">
<div class="main-title new-profile">
new profile
</div>
{{#each profile.properties}}
{{> sliderComponent}}
{{/each}}
</template>
<template name="sliderComponent">
<div class="sliderComponent dragdealer">
<div class="handle">{{label}}</div>
</div>
</template>
Other than onAfterAction which does "buritos" for my use case, where/how can one define an callback that ensures that the template was fully rendered. Or, to what should I subscribe?
Ideally this should be done in your template. In Meteor all templates have onCreated and onRendered callbacks. If you use onRendered, you can be sure that all DOM elements are already there.
Template.sliderComponent.onRendered(function(){
var elements = $('.sliderComponent');
//... do stuff and decorate the elements
});
It is good practice to initialize your template like this. Use Iron Router to parameterize your templates, as you are already doing.

Meteor currentUser

Using the node.js framework Meteor -
how come the currentUser variable is defined in a template such as here:
<template name="main_template">
<div class="container">
{{#if currentUser}}
{{> add_player_form_template}}
{{/if}}
</div>
</template>
but when I call currentUser from the console, it's undefined:
however, Meteor.userId is defined:
why is this?
{{ currentUser}} is a helper in the main_template template.
In your client Javascript you'll need to define that helper method. Something like:
Template.main_template.helpers({
currentUser: function() {
return Meteor.userId();
}
})
This may help too http://docs.meteor.com/#/basic/templates.
{{ currentUser }} is a template helper that simply calls Meteor.user().
In the console, you need to call Meteor.user().

How does Partials / Template inheritance work in Mustache?

I don't really understand partials / template inheritance from Mustache / Hogan.js. As defined here and here you seem to must have two different files to make that work. I use it as follows in my (client side) page:
<template id="server-template">
{{#servers}}
<b>some html and {{> some other which I dont understand how to use}}</b>
{{/servers}}
</template>
<template id="room-template">
I want this in up there. (in the "partials" tag)
</template>
Thanks for helping. I compile them with this:
var source = $('#room-template').html(),
compiled = Hogan.compile(source)
$('#main').html(compiled.render(data))
Is that even possible?
The docs state that you must compile your partials separately, and then pass them to the render function:
In mustache.js an object of partials may be passed as the third
argument to Mustache.render. The object should be keyed by the name of
the partial, and its value should be the partial text.
var roomTemplateSource = $('#room-template').html();
var roomTemplate = Mustache.compile(roomTemplateSource);
Mustache.render(template, view, {
room: roomTemplate
});
<template id="server-template">
{{#servers}}
<b>some html and {{> room}}</b>
{{/servers}}
</template>

Meteor Display Child Array Elements #each

I'm trying to use Meteor's #each to display a JSON Object from Mongo with children. Say it looks like so:
{
data: {dorem: 'ipsum', dolor:'sit'},
amet: 'abcdefg'
}
Using #each, I currently have something like this
<template name="base">
{{#each stuff}}
{{> info}}
{{/each}}
</template>
The info template looks something like this
<template name="info">
{{data.dorem}}
</template>
The method I'm using to generate stuff is
Template.base.stuff = function () {
return DBThatHasStuffInIt.find({sort:{ _id : -1 }});
};
However, it is not working. Nothing is being displayed. The base template has been added, as well.
Does anybody know what the problem might be?
Your find, requires a selector:
return DBThatHasStuffInIt.find({}, {sort:{ _id : -1 }});

The context of "this" in Meteor template event handlers (using Handlebars for templating)

A quick question on the context of the event handlers for templates in Meteor (with Handlebars).
In the section of Documentation on template instances (http://docs.meteor.com/#template_inst) it is mentioned that "Template instance objects are found as the value of this in the created, rendered, and destroyed template callbacks and as an argument to event handlers"
In the Templates section (http://docs.meteor.com/#templates) it says "Finally, you can use an events declaration on a template function to set up a table of event handlers. The format is documented at Event Maps. The this argument to the event handler will be the data context of the element that triggered the event."
Well, this is only partially true. Let's use an example from the docs:
<template name="scores">
{{#each player}}
{{> playerScore}}
{{/each}}
</template>
<template name="playerScore">
<div>{{name}}: {{score}}
<span class="givePoints">Give points</span>
</div>
</template
Template.playerScore.events({
'click .givePoints': function () {
Users.update({_id: this._id}, {$inc: {score: 2}});
});
Here the "this" context of the 'click .givePoints' event handler is indeed the template instance of playerScore. Let's modify the html:
<template name="scores">
<span class="click-me">Y U NO click me?<span>
{{#each player}}
{{> playerScore}}
{{/each}}
</template>
<template name="playerScore">
<div>{{name}}: {{score}}
<span class="givePoints">Give points</span>
</div>
</template>
... and add an event handler for .click-me on the scores template:
Template.scores.events({
'click .click-me': function () {
console.log(this);
}
});
Now, if you click the span, what do you get logged? The Window object! What did I expect to get? The template object! Or maybe the data context, but it's neither. However, inside the callbacks (e.g. Template.scores.rendered = function(){ ... }) the context of "this" is always the template instance.
I guess my real question would be: is this something to do with
a bug in Handlebars, Meteor or somewhere in between?
slightly incomplete documentation on the templates?
me completely misinterpreting the docs or not understanding something fundamental
about Meteor or Handlebars?
Thanks!
This video explains the concepts:
http://www.eventedmind.com/posts/meteor-spark-data-annotation-and-data-contexts.
The direct answer to your question:
The thisArg inside an event handler should point to a data context. But sometimes the data context is undefined. When you use the Function.prototype.call(thisArg, ...) in JavaScript, if the thisArg is undefined (e.g. a dataContext is undefined) the browser will set this equal to window. So, the docs aren't wrong per se but the event handling code isn't guarding against the possibility of a data context being undefined. I'm guessing that will be fixed in short order.
So, what produces a data context for a template? Normally your root template won't even have a data context. In other words, the Template function is called without an object. But if you use the {{#with block helper or the {{#each iterator, a data context will be created for each item in the list, or in the case of the with helper, the object.
Example:
var context = {};
<template name="withHelper">
{{#with context}}
// data context is the context object
{{/with}}
</template>
var list = [ {name: "one"}, {name: "two"} ];
<template name="list">
{{#each list}}
{{ > listItem }} // data context set to the list item object
{{/each}}
</template>
The first parameter in the function is the event. So you could use the target of the event to grab your element.
Template.scores.events({
'click .click-me': function (event, template) {
console.log(event.target);
$(event.target).text("O but I did!");
}
});

Categories

Resources