Meteor - event on {{if currentUser}} content loaded - meteor

I have a template
{{#if currentUser}}
<input id="datetimepicker" type="text" >
{{/if}}
I want do add
$('#datetimepicker').datetimepicker();
But in methods of template:
onCreated
onRendered
content of {{#if currentUser}} is not accessible because collection with user is loaded after template. I can use setTimeout, but this is non stable solution. I can to type in template
{{#if currentUser}}
<input id="datetimepicker" type="text" >
<script>
$('#datetimepicker').datetimepicker();
</script>
{{/if}}
but this is not elegant.
How to catch rendering of content in block {{if currentUser}} in correct way? Or maybe should I not use this syntax generally and there is other manner of checking is user is loaded. If yes, link to proper tutorial please.

The way to do this is to make the content of the if another template, and then use the onRendered or onCreated methods of that template.
{{#if currentUser}}
{{> datePicker}}
{{/if}}
...
<template name="datePicker">
<input id="datetimepicker" type="text" >
</template>
JS:
Template.datePicker.onCreated(() => {
// something
});

#Christian Fritz's answer works well.
In case you don't want to create a new template because of some other issues, you can also try this in the onRendered callback:
Tracker.autorun(function() {
if ($('#datetimepicker')[0]) {
$('#datetimepicker').datetimepicker();
}
});

Related

Comparing current user to a meteor list

I'm currently making a simple web app with meteor.js . I'm trying to implement a simple feature for my fantasy football league's custom site that I'm building.
Here's my code that's not working.
{{#each users}}
{{#if Meteor.userId() {{_id}} }}
{{> ownTradingBlock}}
{{else}}
{{> userTradingBlock}}
{{/if}}
{{/each}}
So basically I want to render a different template if the user in the list of league members is the current user that is logged in. Does anybody have any thoughts on how this is creating an error, and/or if there's a better way to do it?
Here's the error code I'm getting.
.html:67 : expected space
You cannot use a Meteor method within Spacebars. For this you will need to create a helper:
Template.yourTemplate.helpers({
isEq: function (id) {
if (Meteor.userId() === id)
return true;
return false;
}
});
Then in your template:
{{#each users}}
{{#if isEq _id}} }}
{{> ownTradingBlock}}
{{else}}
{{> userTradingBlock}}
{{/if}}
{{/each}}

re-rendering template when changing property from click event

i would like to trigger the visibility of a block in my handlebars template from an onclick function. i can use sessions and a helper function to get this to work but it seems overkill.
<template name="eventlist">
{{#each eventcollection}}
<div class="eventcontent">
name: {{name}} <br>
{{#if showdetail}}
detail: {{detail}}
{{/if}}
</div>
{{/each}}
</template>
could it be possible to make it work somehow like this?
Template.eventlist.events = {
'click .eventcontent': function() { this.showdetail = true}
}
meteor would just need to check if any attribute of this changed after the event completed and then rerender the template
Why bother Meteor? Such things were easy to achieve in the ancient Javascript days:
<template name="eventList">
{{#each eventCollection}}
<div class="eventContent">
name ...
<span class="eventHidden" style="display: none;">
detail ...
</span>
</div>
{{/each}}
</template>
Template.eventList.events({
'click .eventContent': function(e) {
$(e.target).find('.eventHidden').toggle();
},
});

Do I need to Reload the Site in Meteor?

I have this Template:
<template name="body">
{{#if key}}
{{> mite}}
{{else}}
{{> settings}}
{{/if}}
</template>
and
<template name="settings">
<h1>The settings</h1>
<form class="form-inline">
<input id='apiKey' type='text' name='apiKey' placeholder='your API-Key'>
<button id='saveSettings' type='submit' class='btn'>save</button>
</form>
</template>
<template name="mite">
<div>
<h3>...here with key</h3>
<p>
<a id="optout" href="#">not your key?</a>
</p>
</div>
</template>
When I show the settings-form where the user can set the key needed to show the 'mite' template. Now when i 'submit' the form the page get reloaded and the 'mite' template is shown.
On the mite template I'd like to have that link 'not your key?' or something that deletes the key and then shows the settings-form again. It works with a reload... but can't I do this without all the reloading in Meteor? How can i 'call' the template part with the #if in the body template?
-- Renato
You need to bind an event handler to your form and use preventDefault() to stop it submitting. e.g
client side js
Template.settings.events({
'submit':function(event,template) {
event.preventDefault();
var apiKey = template.find('input[name=apiKey]').value;
//..rest of logic to handle submit event
Session.set("key",true);
}
});
You can then use a template helper with Session.get("showthistemplate") to decide whether to show another template or not: (this is a universal helper since you're putting it in and not a template:
Handlebars.registerHelper('key',function() {
return Session.set("key",true);
});

Can Meteor child templates access parent template helpers?

Say we have a parent template and a child template:
<template name="parent">
{{> child }}
</template>
<template name="child">
{{#if show}}
//Do something
{{/if}}
</template>
If we assign 'show' to the parent template:
if (Meteor.isClient){
Template.parent.show = function(){
return Session.get('isShowing');
}
}
Is there any way for the child template to have access to it?
Edit
You could make a universal handlebars helper so you could use Sessions values anywhere in your html:
Client js
Handlebars.registerHelper('session', function(key) {
return Session.get(key);
});
Client HTML
<template name="child">
{{#if session "show"}}
//Do something
{{/if}}
</template>
Similarly, you could also use {{session "show"}} / {{#if session "show"}} in your parent template and not have to use the Template.parent.show helper anymore.
Regarding the use of ../ notation. There are certain scenarios it may not work: https://github.com/meteor/meteor/issues/563. Basically it works within {{#block helpers}} but not with templates, but it would work in a block helper if it contains a subtemplate.
<template name="child">
{{#if ../show}}
Do something
{{/if}}
</template>
You can also register a common helper :
Template.registerHelper('isTrue', function(boolean) {
return boolean == "true";
});
And call it just like that in your html:
<input type="checkbox" checked="{{isTrue attr}}"/>

How to render a Meteor Template from Collection of Template names?

I have three simple Templates in Meteor, and a Collection on the server with any combination of their names. I want to be able to render these templates dynamically based on which of their names are in the Collection.
Currently I am trying to accomplish this by using the client to subscribe to the Collection, and access the names through a template function. Unfortunately, if I try to run ">" on the names, Meteor attempts to render the variable name instead of the Template pointed to by its value.
So instead of rendering the html in template1, template2, and template3, the output is merely their names on the page: "template1 template2 template3".
Here is the code I've been using, I hope there's a way to solve my issue without having to run Meteor.render manually.
Server js:
TemplatesToRender = new Meteor.Collection("templatesToRender");
TemplatesToRender.insert({templateName: "template3"});
TemplatesToRender.insert({templateName: "template2"});
Client html:
<body>
{{#each templatesToRender}}
{{> templateName}} // meteor trying to render a template
// called "templateName" instead of the
// variable inside templateName.
{{/each}}
</body>
<template name="template1">
<span>Template 1</span>
</template>
<template name="template2">
<span>Template 2</span>
</template>
<template name="template3">
<span>Template 3</span>
</template>
You can make a render helper:
Handlebars.registerHelper('render', function(name, options) {
if (Template[name])
return new Handlebars.SafeString(Template[name]());
});
And use it with
{{render templateName}}
You might want to try this
in your html
<body>
{{> templateToRender}}
</body>
<template name="templateToRender">
{{! use below to detect which template to render}}
{{#if templateName "template1"}}
{{> template1}}
{{/if}}
{{#if templateName "template2"}}
{{> template3}}
{{/if}}
{{#if templateName "template3"}}
{{> template3}}
{{/if}}
</template
<template name="template1">
<p>this is template1</p>
</template>
<template name="template2">
<p>this is template2</p>
</template>
<template name="template3">
<p>this is template3</p>
</template>
in your script
Template.templateToRender.templateName = (which) ->
# if user have a field like templateName you can do things like
tmplName = Meteor.user().templateName
# Session.equals will cause a template render if condition is true.
Session.equals which, tmplName
Meteor 1.0 just came out today, and I just want to update this for 2014 :)
https://docs.meteor.com/#/full/template_dynamic
{{> Template.dynamic template=template [data=data] }}
Sample Usage:
{{#each kitten}}
{{> Template.dynamic template=kitten_type data=this }}
{{/each}}

Resources