Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iron:router will not re-render after route change with same template

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?

like image 533
willemx Avatar asked Nov 17 '14 10:11

willemx


2 Answers

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.

like image 166
hecht Avatar answered Sep 23 '22 01:09

hecht


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>
like image 26
elpddev Avatar answered Sep 22 '22 01:09

elpddev