问题
How can I make Iron:router re-render a template?
I have this html:
<head>
</head>
<body>
</body>
<template name="mainLayout">
<a href="{{pathFor route='list'}}">list</a>
<a href="{{pathFor route='find' query='q=xxx'}}">find</a>
{{> yield}}
</template>
<template name="listTemplate">
<p>list</p>
</template>
and this js:
Router.configure({
layoutTemplate: 'mainLayout'
});
Router.route('/list', {
name: 'list',
template: 'listTemplate'
});
Router.route('/find', {
name: 'find',
template: 'listTemplate',
data: function () {
return this.params.query;
}
});
if (Meteor.isClient) {
Template.listTemplate.rendered = function () {
if (this.data)
console.log('find ' + this.data.q);
else
console.log('list all');
};
}
When I click on the links to switch views (simulated here with console.log), the route does change, but the template is not re-rendered. Is there a way to force iron:router to re-render?
回答1:
You can try something like this:
Router.configure({
layoutTemplate: 'mainLayout'
});
Router.route('/list', {
name: 'list',
template: 'listTemplate',
action: function() {
this.state.set('query', this.params.query);
}
});
Router.route('/find', {
name: 'find',
template: 'listTemplate',
data: function() {
return this.params.query;
},
action: function() {
this.state.set('query', this.params.query);
}
});
if (Meteor.isClient) {
Template.listTemplate.rendered = function() {
this.autorun(
function() {
if (this.state.get('query'))
console.log('find ' + this.data.q);
else
console.log('list all');
}
);
};
}
The rendered method isn't reactive, that's why you need an autorun. The template "this.data" isn't reactive so you're gonna need a reactive var to do that, either a Session variable, a controller state, or some kind of reactive var.
You may need to add the reactive-var package depending on what approach you take.
回答2:
Setting the router controller state did not work for me. The answer Antônio Augusto Morais gave in this related github issue worked. Using the Session to store the reactive var to trigger the autorun reactiveness. It's a hack, but it works.
## router.coffee
Router.route '/profile/:_id',
name: 'profile'
action: ->
Session.set 'profileId', @params._id
@render 'profile'
## profile.coffee
Template.profile.onCreated ->
@user = new ReactiveVar
template = @
@autorun ->
template.subscription = template.subscribe 'profile', Session.get 'profileId'
if template.subscription.ready()
template.user.set Meteor.users.findOne _id: Session.get 'profileId'
else
console.log 'Profile subscription is not ready'
Template.profile.helpers
user: -> Template.instance().user.get()
## profile.html
<template name="profile">
{{#if user}}
{{#with user.profile}}
<span class="first-name">{{firstName}}</span>
<span class="last-name">{{lastName}}</span>
{{/with}}
{{else}}
<span class="warning">User not found.</span>
{{/if}}
</template>
来源:https://stackoverflow.com/questions/26970808/ironrouter-will-not-re-render-after-route-change-with-same-template