I have a project that involves a dozen routes, all of which require a navbar and various other pieces that I would like to include in my layout template.
My issue is that I have one and only one page that doesn't need a navbar. I could solve this by taking the navbar out of the layout template and putting the navbar manually in every page that needs it, but that doesn't seem like an elegant solution.
Is there a way to exclude a particular route from including a piece of the layout template?
Why not assigning this particular route another layout who doesn't include the navbar then ?
HTML
<template name="mainLayout">
{{> navbar}}
{{> yield}}
{{> footer}}
</template>
<template name="withoutNavbarLayout">
{{> yield}}
{{> footer}}
</template>
JS
Router.configure({
layoutTemplate:"mainLayout"
});
Router.route("/withoutNavbar",{
layoutTemplate:"withoutNavbarLayout"
});
Here is another simple solution to the problem.
Just set the layoutTemplate to null for the specified page you want to exclude layout. For example, here we will remove the layout and navigation for the login page:
Router.route('login', {
layoutTemplate: '' //set the layoutTemplate to null for the login route
});
Hope it helps.
Related
i have started using meteor/blaze/FlowRouter recently and stuck on one issue
i need to display my custom loader div which will be shown whenever page template is in transition mode like loading content or requesting data from api or search users data etc
is there any way do to it in one place ? ... i don't want to add html content of loader in every page and handle it by function calling as it will be repetition of code
You can use percolate:momentum package from atmosphere.
First, install momentum:
meteor add percolate:momentum
Then, create a layout template:
<template name="appBody">
{{#momentum plugin="fade"}}
{{#if Template.subscriptionsReady}}
{{> Template.dynamic template=main}}
{{else}}
{{> AppLoading}}
{{/if}}
{{/momentum}}
</template>
If your subscriptions is ready, then Blaze will render template {main} specified in router. Otherwise, will render your AppLoading Template.
And you need to create the AppLoading template too:
<template name="AppLoading">
<!-- Your Loading div here -->
</template>
<template name="orderForm">
{{> photographyServicesForm}}
{{> videographyServicesForm}}
{{> onlineProductsForm}}
</template>
If I go to the orderForm page is there a way to get the data inside of the orderForm Blaze template instance when I'm in Chrome Console? I know how to get it inside the orderForm callbacks, events, helpers, and inside the HTML, but I want to be able to easily check up on it and even update it from the Chrome Console.
I also know that there are four different template instances when I go to this orderForm. Obviously Template.orderForm doesn't work because it's not the current template instance.
EDIT
Here's the answer:
<template name="orderForm">
<div id="orderForm">
{{> photographyServicesForm}}
{{> videographyServicesForm}}
{{> onlineProductsForm}}
</div>
</template>
Blaze.getData($('#orderForm')[0])
It should be noted that the same data available on the orderForm template is also available to its child templates - photographyServicesForm, videographyServicesForm, onlineProductsForm
You want to check out Blaze.getData and Blaze.getView.
With Blaze.getData you can simply do this:
Blaze.getData(document.querySelector('.someelement'))
This works pretty well, but you have to have an element inside the template-instance you can query for.
I am currently going through the Meteor tutorial (https://www.meteor.com/try), and have come across something about Templates that puzzles me.
In the tutorial, a simple "Todo List" application gets created. In this app, the following HTML is placed into the simple-todos.html file:
<!-- simple-todos.html -->
<head>
<title>Todo List</title>
</head>
<body>
<div class="container">
<header>
<h1>Todo List</h1>
</header>
<ul>
{{#each tasks}}
{{> task}}
{{/each}}
</ul>
</div>
</body>
<template name="task">
<li>{{text}}</li>
</template>
Then, the following JavaScript is placed into the simple-todos.js file:
// simple-todos.js
Tasks = new Mongo.Collection("tasks");
if (Meteor.isClient) {
// This code only runs on the client
Template.body.helpers({
tasks: function () {
return Tasks.find({});
}
});
}
At this point, the example works exactly as intended. However, as I poke around in the documentation, as well as look at other examples on the web, I have noticed slightly different syntax: using Template.myTemplate instead of Template.body.
So, out of curiosity, I altered my JavaScript file to read:
Template.task.helpers({ ...
instead of:
Template.body.helpers({ ...
However, when I run the application now, the client does not display the data from the collection. I don't get any errors about undefined types, like I do if I misspell the template name in the JavaScript, so it seems that it is resolving the template correctly. But why isn't it getting used or rendered?
And to go a little further: when is it appropriate to use Template.myTemplate and when is it appropriate to use Template.body?
The helpers code only works for the template it's attached too.
So, code that works for Template.task will only apply to templates named "task".
Template.body is like the one-off that exists because it would be weird if it didn't. It's a way for you to specifically target the <body>, even though technically, there's no template named "body".
So, what is going on:
Parent template = body
Child template = task
Your logic says:
In the parent template, for each task that we find, render an instance of the child template "task".
If you change your helper from body to task, you won't get any output at all, unless you mimic the pattern that's already happening:
<template name="task">
{{#each tasks}}
do something
{{/each}}
</template>
That's because <body> is the parent template, and you should treat it as such:
<template="body>stuff that normally goes in an HTML body here</template>
When you remove the helpers for the body, then no data gets displayed at all because helpers pass data into the template. And with no helper for the template i.e. the body, you get no data.
It is very useful to use template.find to locate DOM elements inside a specific template instance. But what happens when the template iterates {{#each}} over some tags without using a sub-template?
<template name="top">
{{#each items}}
<img src="{{src}}">
Click me
{{/each}}
</template>
Tempalte.events(
'click a': (event, template) ->
template.find('img') # This doesn't do the trick
# Is there a better way?
)
Is there a way to easily access the img element associated with the click event?
I know I can use event.target or create another template an use it inside the {{#each}} block. I wonder if there is a better/shorter way to do it.
You could add an #index to the img to make it possible to select it (using js or CSS). How to get index in Handlebars each helper?
I am using Meteor 0.5.2 and trying to solve what seems to me is an obvious pattern that should have an easy solution.
I have a template that should return different chunk of data in each of template instances.
For example - I have a template showing TV program - show by show.
Then I need to display two instances of the same template with different data - one with past shows and one with upcoming shows.
So I have a tv program template:
<template name="tv_program">
{{#each shows}}
...
</template>
Ideally I would like do something like:
{{> tv_program past_shows}}
...
{{> tv_program upcoming_shows}}
to pass a parameter to tv_program template instance that I can read from JavaScript and adjust the mongo queries.
Currently I have copy/pasted my template/js code and adjusted the mongo queries but there has to be a better way.
I looked into partials/helpers with arguments but that doesn't seem to be the solution to my problem.
Thanks, Vladimir
You're approaching the problem at the wrong level. Rather than trying to tell your code what to do from your templates, you should tell your template what to do from your code. For instance:
Template.past_shows.shows = function() { return shows(-1); }
Template.upcoming_shows.shows = function() { return shows(1); }
function shows(order) {
return Shows.find({}, {$sort: order});
}
<template name="past_shows">
{{#each shows}}
{{> show}}
{{/each}}
</template>
<template name="upcoming_shows">
{{#each shows}}
{{> show}}
{{/each}}
</template>
<template name="show">
<li>{{_id}}: {{name}}</li>
</template>
If you are using a state machine for your app, such as meteor-router, you can use one template and populate it with upcoming or past shows depending on app state.