My route:
Router.route('/profile/:_id', {
layout: 'appTabs',
template: 'appProfile',
autoRender: false
});
My Layout:
<template name="appTabs">
...
<a href="/profile/{{getUserId}}">
...
<section>
{{> yield}}
</section>
...
</template>
My Template:
<template name="appProfile">
<section>
<div>my profile</div>
</section>
</template>
Trouble is that my route automatically renders. I have a link in my template, I want to wait for it to be clicked before the template is rendered. How do I achieve this?
Related
I have a template (navBarContent) that I is passed a "title" when I insert it.
I am then able to access {{title}} within that template, but it is not possible to access it within a {{#contentFor}} block embedded in the navBarContent template:
<template name="map">
{{>navBarContent title="MAP"}}
... other content ...
<template>
<template name="navBarContent ">
{{title}}
{{#contentFor "headerTitle"}}
<h1 class="title">{{title}}</h1>
{{/contentFor}}
</template>
I already tried to "forward" the title:
<template name="navBarContent ">
{{title}}
{{#contentFor "headerTitle" title="MAP"}}
<h1 class="title">{{title}}</h1>
{{/contentFor}}
</template>
which produces the following error:
First argument must be a function, to be called on the rest of the arguments;
EDIT:
Ok. I think the data scopes are a the following:
<template name="layout">
{{> yield "headerTitleRenderedInLayout"}}
{{> yield}}
</template>
<template name='map'>
{{> yield "headerTitleRenderedInTemplate"}}
{{>navBarContent title="PARAMETER_TITLE"}}
</template>
<template name="navBarContent">
{{title}} <!-- output: PARAMETER_TITLE -->
{{#contentFor "headerTitleRenderedInLayout"}}
<h1 class="title">{{title}}</h1> <!-- output: LAYOUT_DATA_TITLE -->
{{/contentFor}}
{{#contentFor "headerTitleRenderedInTemplate"}}
<h1 class="title">{{title}}</h1> <!-- output: TEMPLATE_DATA_TITLE -->
{{/contentFor}}
</template>
Above outputs are produced when I use the following router options:
Router.route('/map', function () {
this.layout("layout", {
data: function() {
return { title: "LAYOUT_DATA_TITLE" }
}
});
this.render('map', {
data: function() {
return { title: "TEMPLATE_DATA_TITLE" }
}
});
});
My app has a navbar that is defined in my main layout and I therefore need to set the datacontext for the layout in my route. So far so good, but I want to set that data context based on the value that I pass via:
{{>navBarContent title="PARAMETER_TITLE"}}
This is just a cosmetic thing, because I prefer to define my navbar content in the different templates rather than the routes.
It works when you pass the data context to the render function because Iron Router handles the contentFor block:
Router.route('/', function() {
this.render('map', {
data: function() {
return { title: 'MAP' }
}
});
});
Then the following template shows MAP twice:
<template name="map">
{{> navBarContent }}
{{> yield 'anotherBlock'}}
</template>
<template name="navBarContent">
<div>
In "map": {{title}}
</div>
{{#contentFor 'anotherBlock'}}
<div>
In contentFor: {{title}}
</div>
{{/contentFor}}
</template>
I'm having trouble understanding why AutoForm is not working 100% here. The client-side validation works but submitting the form is not calling the meteor method insertQuestion.
As soon as I replace the contents of the modal template with the modalQuestion template it works and the meteor method is called. So my best guess here is that it has got something to do with {{> Template.dynamic }} include but haven't been able to solve this problem myself.
Can anyone tell me why the dynamic template include is not playing nice here?
layout.html
<template name="layout">
{{> modal}}
</template>
layout.js
Session.set('modalData', {template: "modalQuestion", title: "Test"});
modal.js
Template.modalBlock.onRendered(function () {
this.autorun(function() {
if (Session.get('modalData')) {
$('#modal').modal();
}
});
});
modal.html
<!-- A template to include in index.html that dynamically renders the a modal template -->
<template name="modal">
{{#if modalData}}
{{> Template.dynamic template=modalData.template data=modalData}}
{{/if}}
</template>
<!-- A generic block to be used by our modals -->
<template name="modalBlock">
<div id="modal">
<header>{{title}}</header>
{{> Template.contentBlock }}
</div>
</template>
<!-- A specific modal template -->
<template name="modalQuestion">
{{#modalBlock title=title}}
{{ #autoForm schema=SchemasQuestion meteormethod="insertQuestion" type="method" id="insertQuestionForm" class="form" }}
{{> afQuickField name="text" label=false placeholder="schemaLabel" }}
<button type="submit" class="button">Submit</button>
{{ /autoForm }}
{{/modalBlock}}
</template>
I have a list template (#each) in a package that I plan to use across many different collections. Since the template is in a package they are not easily customizable. So I figured this was a great example to use Template.dynamic. Everything works except passing data.
.. I pull the data into the routed page and manipulate the data to match the dynamic template.
Template.usersIndex.helpers({
items: function() {
var users = Meteor.users.find({}).fetch();
var items = users.filter(function(user) {
return user;
}).map(function(user){
return {
name: user.profile.name,
description: user.emails[0].address,
tidbit: "hello"
};
});
return items
}
});
... the data passes perfectly to the usersIndex template.
<template name="usersIndex">
<div id="gc-users-index-navbar">
<h2>Title</h2>
</div>
<div id="gc-users-index" class="inner-content">
{{> Template.dynamic template="strataIndexItem" data="items" }}
</div>
</template>
... But no dice, the dynamic template is rendered but no data.
<template name="themeIndex">
<div class="list-group">
{{#each items }}
<div class="list-group-item">
<div class="row-content">
<div class="least-content">{{tidbit}}</div>
<h4 class="list-group-item-heading">{{name}}</h4>
<p class="list-group-item-text">{{description}}</p>
</div>
</div>
<div class="list-group-separator"></div>
{{/each}}
</div>
</template>
You pass data as string?
{{> Template.dynamic template="strataIndexItem" data="items" }}
You should pass data as variable, without ""
{{> Template.dynamic template="strataIndexItem" data=items }}
Also check if your strataIndexItem template is named strataIndexItem:
<template name="strataIndexItem">
...
</template>
I have 2 templates:
1) mainLayout.html -> general layout which must be used by all pages. (e.g. page title, navbar, footer)
Router.configure({
layoutTemplate: 'mainLayout'
})
<template name="mainLayout">
{{> header}}
<div class="container-fluid">
{{> yield}}
</div>
</template>
2) specialLayout.html -> custom layout which is inheriting main-layout.html but with additional template (e.g. side/tab menu)
How should I define specialLayout? Note that specialLayout should have the title, navbar, and footer defined in mainLayout.
If I have route X which want to use specialLayout, how should I write it?
I don't know any simple method at this moment, but most things can be achieved by several less elegant ways:
Copy your common parts into separate templates and use them in both layouts, i.e.:
<template name="mainLayout">
{{> navbar}}
<div>
{{> content}}
</div>
{{> footer}}
</template>
<template name="specialLayout">
{{> navbar}}
<div>
{{> content}}
{{> sidebar}}
</div>
{{> footer}}
</template>
Make your special part an option in the main layout instead of a separate one:
<template name="mainLayout">
...
<div>
{{#if layout.renderSidebar}}
<div class="col-2">>
{{> yield 'sidebar'}}
</div>
{{/if}}
<div class="{{#if layout.renderSidebar}} col-10 {{else}} col-12 {{/if}}">
{{> yield}}
</div>
</div>
...
</template>
Then in the appropriate routes enable sidebar in the data:
this.map('pathName', {
...
data: function() {
return {
layout: {renderSidebar: true},
...
};
},
});
I am developing a meteor.js application. I have two main templates/pages, home.html and groups.html. I render these templates according to the selection of main menu. In home template, I just show basic informations about the website. But in groups template, I have side menu which has timeline, chat, group blog options, and according to the selection of side menu, I render timeline or chat or groupblog templates inside groups template. I succeeded this with two different methods.
Can you please tell me if any of them is correct approach, and if they both are, which one is better to use?
In the first approach, is there any way to wait to render sub-template until data is ready, like waitOn property in iron-router?
First approach: I am using dynamic template, and rendering and setting data contex of sub-templates by using Session variable.
layout.html
<template name="layout">
<div>
{{> header}}
<div id="main" class="container">
{{> yield}}
</div>
</div>
</template>
groups.html
<template name="groups">
<div class="row">
<div class="row-fluid">
<div class="col-md-9 col-lg-9">
{{> dynamictemplate}}
</div>
</div>
</div>
</template>
dynamictemplate.html
<template name="dynamictemplate">
{{#DynamicTemplate template=getTemplate data=getData}}
Default content when there is no template.
{{/DynamicTemplate}}
</template>
dynamictemplate.js
Template.dynamictemplate.helpers({
getData: function () {
var tempname="timeline";
if(Session.get("menuitemselected")!=null){
tempname =Session.get("menuitemselected");
}
if(tempname=="timeline"){
return {test:123};
}else if(tempname=="calendar"){
return {groupId:this._id};
}
},
getTemplate: function () {
var tempname="timeline";
if(Session.get("menuitemselected")!=null){
tempname =Session.get("menuitemselected");
}
return tempname;
}
});
Second approach, I am defining new routes for all sub-templates in routes, and I am using yield with region property in home template.(I do not know if i am supposed to use yield in any place other than layout.html)
layout.html
<template name="layout">
<div>
{{> header}}
<div id="main" class="container">
{{> yield}}
</div>
</div>
</template>
groups.html
<template name="groups">
<div>
<div class="col-md-3">
{{> sidemenu}}
</div>
<div id="main" class="col-md-9">
{{> yield region="detailrender"}}
</div>
</div>
</template>
router.js
.....
this.route('groupdetail', {
path: '/groupsmain/:_id',
layoutTemplate: 'layout',
yieldTemplates: {
'timeline': {to: 'detailrender'}
},
data: function() { return Groups.findOne(this.params._id);
}
});
this.route('groupdetailcalendar', {
path: '/groupsmain/:_id/calendar',
layoutTemplate: 'layout',
template: 'groupdetail',
yieldTemplates: {
'calendar': {to: 'detailrender'}
},
data: function() { return Groups.findOne(this.params._id);
.....
});