Change some html in layout template when on a certain route (with iron-router and meteor.js) - meteor

I have a template I have set up as my layout using iron-router:
Router.configure({
layoutTemplate: 'main'
});
Within this layout, I have a line of html that I would like to be changed on certain routes.
My ideas is doing something like:
{{#if landing }}
<div id="page-wrapper">
{{/if}}
However, how do I implement this for a certain route? I want this variable to be true on every route except for 1.

I think that this kind of "change the template based upon what route I'm on" logic fits best into the use of a template for that route (and any others that will make this same change. Depending on the change required, you may be able to call in your base Template into the modified template.
Example:
Router.route('/yourSpecialRoute', function(){
this.layout('OtherLayout');
});
See the Layout docs - I borrowed the syntax of Setting Region Data Contexts
Having said, if you prefer not to switch layouts per route, consider setting a data on your route (something like {data: item} as shown here in the iron:route readme which can then be read by a global helper (Template.registerHelper syntax) - this will at least make it consistent across your routes / templates.

Related

Iron-Router dynamic templates in layout like in Flow-Router

How can i render dynamic templates via layout in Iron Router?
For example in Flow-Router in layout i can define some dynamic templates:
newsRoutes.route('/',{
action:function(){
BlazeLayout.render("layout",{top:"digest",left:"post_list",right:"chat"});
}
});
And then i can define another route with another parameters:
adminRoutes.route('/',{
action:function(){
BlazeLayout.render("admin_layout",{top:"admin_user_list"});
}
});
And Flow-Router will not render nothing in left and right positions.And it is good for me.
But with named {{>yield}} regions in Iron:Router i can't do that. Because Iron:Router save {{>yield}} regions from route to route, and it can be only rewriten by redefined regions. How can i prevent rendering {{>yield}} regions if it not defined in current route?

Meteor & Flow Router: Marking Dynamically generated paths as 'active'

Needless to say, my experience with Meteor is lacking. I come from a Rails background, where you can do a lot more logic (and magic) in your views than Meteor.
The situation: I've got some routes that look like /things/:_id, and I've named that route 'thing' because it shows only one thing of a user's many owned things:
FlowRouter.route('/things/:_id', {
name: 'thing',
action() {
BlazeLayout.render('appPage', {app: 'thing', sidebar: "thingsListOnThing", header: 'thingTitle'});
}
});
As you can see, I'm also loading a template I've built to list all of the user's owned things on the sidebar for easy navigation. That template, thingsListOnThing is the target of this question.
Get the gist? I'm able to mark the route that dislays a template with a complete list of a user's things as active using zimme:active-route like so:
// A list of all a user's things
<div class="{{isActiveRoute name='things' class='is-active'}}">
List of Things
</div>
This package is great, but it won't help me with routes that look like /things/:_id because, then every link to each individual thing would be is-active on any thing page, not just the one where the current path's :_id matches the _id of the active thing.
I'm really kind of stuck here. My first guess would be to use template helpers, but I'm confused as to where to get started with that.
If need be, please as me to upload any piece of my code you require. I figured it's such a generic question that you guys probably don't need to see all of my code to understand what I'm trying to accomplish.
Using: zimme:active-route
Template Helpers
Template.listOfThings.helpers({
activeListClass(page) {
const active = ActiveRoute.name('thing') && FlowRouter.getParam('_id') === this._id;
return active && 'active';
},
});
Template HTML:
<a class="{{isActivePath 'thing'}}" href="/things/{{_id}}">
<div class="thingListItem {{activeListClass page}}">
{{title}}
</div>
</a>

Where does Meteor.subscribe() belong?

I just noticed that my subscription code "Meteor.subscribe('my-publications')" at the top of my JS file affects ALL my templates, not just the template that the JS file is created for.
This was unexpected because all the demos did it this way.
Where is the subscription code suppose to be in if I want it to affect one template only? Inside Template.name.created()?
Don't assume the only data in minimongo is what is relevant to your template. Be specific when selecting your data for the template.
You have several options as far as subscriptions go, the most common by far is adding a subscription to the waitOn section of your routes definitions. Using waitOn will result in the subscription being unsubscribed when the route is no longer in use.
Router.map(function() {
this.route('route', {
waitOn: function(){ return Meteor.subscribe("yourSub"; }
});
});
You can also subscribe per template. A package I've created for this purpose can be added via
meteor add elevatedevdesign:template-subscriptions
This pattern will also be coming soon as a part of blaze, but with some slight differences in how you call it. This will automatically unsubscribe when the template is no longer active. It also allow's subs-manager to be subscribed to on template destruction.

right way to use subscriptions in meteor

In my meteor app I have all pages that needs to load one or more documents from elements collection and a couple of pages that loads documents from items collection;
I have the two publish functions for the two collections, but now I'm trying to understand the best way to subscribe them;
currently I'm subscribing elements in a file in the /client directory:
Meteor.subscribe("elements");
This will make the subscription on application start;
in the other case, since the items to be loaded are a little more, I've decided to use the subscription option in iron router:
subscriptions: function() {
return Meteor.subscribe("items");
}
The first difference I can see is that it seems that elements, once started the application, will not take time anymore to load (navigating through pages takes no time for loading);
on the other hand, every time I open the page that loads items, (event without a refresh) takes the loading time again;
Would be probably not the best solution to subscribe also items on application start, since they are only needed if you visit their specific route (elements otherwise are needed everywhere);
but there is a way to avoid reloading them from the server every time I ask the route again?
Also thinking about elements, they are not needed all in all pages: avery page need just one or two of them; so it would be probably more corret to load just the one or two that are really needed...
How subscriptions should be managed in your opinion?
I cover some of the trade-offs in my answer to this question. Here's how we use do this at Edthena using the subscriptions manager package:
// Allow the subman to cache a lot of subscriptions for a very long time
var subman = new SubsManager({cacheLimit: 100, expireIn: 864000});
// This is a global subscription that we may need to wait on later
subman.subscribe('sub1');
// This is a global subscription that we don't need to wait on
Meteor.subscribe('sub2');
Tracker.autorun(function() {
if (Meteor.userId()) {
// Add subscriptions which should be loaded globally but only
// after the user logs in.
Meteor.subscribe('sub3');
}
});
var PostController = RouteController.extend({
waitOn: function() {
// Use subman only if we want to cache the subscription between routes.
// Note that in the case of sub1, the previous handle will be reused
return [
subman.subscribe('sub1'),
subman.subscribe('sub4'),
Meteor.subscribe('sub5')
];
}
});
It's a matter of preference, but I think the simplest answer is that you can still use Iron Router's subscriptions option whilst centrally subscribing:
Subscription file:
Subscriptions = {
elements: Meteor.subscribe('elements'),
...
};
Router:
subscriptions: function() {
return Subscriptions.elements;
}
All the router needs is the handle which is returned by Meteor.subscribe, it doesn't actually have to do the subscribing. If you store these handles in a (sensibly named) global object, you can then pass them to the relevant router function when you need them.
First, install IronRouter enter; at the command prompt, enter "meteor add iron:router"; doing so will add that routing package.
So that your "raw" or base URL doesn't throw a routing exception, add this to the top of your .js file (above/outside the "isClient" and "isService" blocks):
Router.route('/');
Add a template or two (or more) to your project's .html file (you can use Notepad or Notepad++ for this, but I recommend the free (and "hackable") Atom editor, from Github, with the Meteor helper packages added. The project will be in a subfolder of whatever folder you were in when you entered the "meteor create" command. To download the Atom Editor, click this.
BTW, the video of the futuristic/pastistic coding family on the Atom Editor site is a gas, man!
Getting back to adding templates; as an example, here are a couple of templates I added:
<template name="garrapatabeach"><p>Here's a picture of Garrapata Beach; early morning;
long exposure.</p>
<p class="location">Garrapata Beach.Garrapata State Park.Big Sur.Monterey County.California</p>
<img height="600" src="/images/garrapataBeach.jpg" width="900" />
</template>
<template name="garrapataturnout"><p>Here's a picture from the first Garrapata turnout;
long exposure</p>
<p class="location">First Turnout.Garrapata State Park.Big Sur.Monterey County.California</p>
<img height="600" src="/images/GarrapataTurnout1.jpg" width="900" />
</template>
Now, add routes for those templates in the same part of the project's .js file where you added the "home" ("/") route in the .js file, so that it looks like this (the routes match the template names):
Router.route('/');
Router.route('/garrapatabeach');
Router.route('/garrapataturnout');
Note: This supposes you have added a "public" folder to your project, and an "images" folder beneath that, and that you have images with the names indicated in that images folder. If you want to "play along," you can download those images from dplatypus.meteor.com/garrapatabeach and dplatypus.meteor.com/garrapataturnout; otherwise, simply change the names of the jpgs and use your own images.
You will now be able to view your templates by navigating to the links given above (to run it, simply enter "meteor" at the command prompt while in the project's folder, and navigate to localhost:3000). However, to make it "more better" (so that the main page is not naked as a jaybird), we'll put some anchor tags/links in the main template, like so:
<body>
{{> main}}
</body>
<template name="main">
Garrapata Beach
Garrapata Turnout
</template>
Now the links will display when you navigate to localhost:3000, and clicking on them will route you to the appropriate page/template. To continue, just add another template, along with its corresponding routing entry and anchor tag/link.

What is Template.myTemplate.helpers(helpers) for and why should I use it?

In Meteor, if the below is my HTML,
<template name="myTemplate">
The value is {{value}}
</template>
I can define the value in two ways
Template.myTemplate.helpers
value: ->
'insideHelper1'
Template.myTemplate.value =
'outsideHelper1'
The first way is using helpers as documented here (http://docs.meteor.com/#template_helpers) whereas the second way is using the Live Template examples as defined here (http://docs.meteor.com/#livehtmltemplates)
Just wondering, what is the difference between the two and when should I use one over the other?
They're exactly the same.
If you use .helpers, it actually just adds it to Template..
It depends on your coding style. You may prefer to use .helpers since it makes cleaner code if you have many helpers on the same template.
One small technically way they're different is Template.helpers adds the helpers to your Meteor app when your Meteor app starts up, whereas using the Template.helpername adds it before. So if you need to overwrite any helpers, you could use the .helpers method. The one that runs last will have the active helper.

Resources