I have a route like this:
Router.route('/box', function () {
this.render('boxCanvasTpl');
},{
name: 'box',
layoutTemplate: 'appWrapperLoggedInTpl',
waitOn: function() {
console.log("Box route ran ok.");
return [
Meteor.subscribe('item_ownership_pub', function() {
console.log("subscription 'item_ownership_pub' is ready.");
}),
Meteor.subscribe('my_items', function() {
console.log("subscription 'my_items' is ready.");
})
];
}
});
... and I am clicking a link in a Template like this:
<a href="/box?box=123" class="box-num-items">My Link</a>
I receive the 'Box route ran ok.' message, but some reason the page does not navigate to the given URL. I have added console.log code in the funciton that is run when the 'boxCanvasTpl' is rendered, but these aren't showing in the browser console. It seems that something inbetween is stopping the templkate from re-rendering, but can't put my finger on it - any ideas?
- ANSWER -
- ANSWER -
There are some properties of Iron Router that you need to be aware of.
Say that the user is currently already on
/boxes
and there is a box
template that renders for that path. If you:- click on a link
<a href="/boxes?box=123">Click Me</a>
or
- click on a link
<a href="{{pathFor 'box'}}">Click Me</a>
Iron Router will NOT re-render the template because it already exists on the page. It will also NOT re-render the template if the
box
template happens to be a partial template that is already rendered on the page that you're on and also exists on the page that you want to navigate to.
Since it doesn't re-render, any code you have inside
Template.box.onRendered
will also not run again.
This behavior is most common in your
layout
, header
, and footer
templates. For many users, these templates are used for all of a website's pages, regardless of path. Because the layout, header, and footer template is rendered on a person's first visit to the site, they won't be re-rendered ever again if the user decides to navigate to other parts of the site using the same templates, so the code inside Template.layout/header/footer.onRendered
won't fire.
Also note - even if a reactive Spacebars helper changes the physical look of the layout / header / footer, it doesn't qualify as an actual
render
, so reactive updates to the template do not trigger the onRendered
callback.
The lack of re-rendering is what gives Meteor that "snappy" feel.
EDIT
Try to code in a reactive, event-driven style. Try not to think too much in a render / re-render sense.
- You go to
/box
- You click on a link for
/box?box=2342
- Get your params or query in Iron Router
- In Iron Router use the data from the params or query to set the
data context
for the template. - Grab stuff from the data context as needed inside of the template's
.onRendered
,.events
, and.helpers
callbacks. - Set Session vars as necessary and use them in helpers to give reactive changes to the page without having to re-render a template. Also use events to trigger updates to the session vars to, again, trigger reactive changes to the page.
Try this:
afterwards, go to /test?BUNNIES=lalalala
check out the console logs
test.html
<template name="test">
{{myData}}
</template>
test.js
Template.test.helpers({
myData: function() {
console.log("data context accessed from test.helpers: ", this);
console.log("this.BUNNIES accessed from test.helpers: ", this.BUNNIES);
return this.BUNNIES;
}
});
Template.test.onRendered(function() {
console.log("data context accessed from test.onRendered: ", this.data);
});
Template.test.events({
'click': function(){
console.log("data accessed from test.events: ", this);
}
});
router.js
Router.route('/test', function() {
console.log("routed!");
this.render('test');
}, {
name: 'test',
data: function(){
//here I am setting the data context
// for /test?BUNNIES=1234
var query = this.params.query;
console.log("query: ", query);
return query;
},
waitOn: function() {
console.log("waitOn is running (should see this message once for each subscription)");
return [
Meteor.subscribe('item_ownership_pub'),
Meteor.subscribe('my_items')
];
}
});
way cleaner way of writing router
Router.route('/test', {
waitOn: function() {
console.log("waitOn is running (should see this message once for each subscription");
return [
Meteor.subscribe('item_ownership_pub'),
Meteor.subscribe('my_items')
];
},
data: function(){
var query = this.params.query;
console.log("query: ", query);
return query;
},
action: function(){
console.log("this will re-render if url params changed");
this.render();
}
})
0 comments:
Post a Comment