Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent Meteor/Iron Router from reloading when changing Routes

I'm noticing that every time Meteor/Iron Router changes routes, the entire page gets refreshed.

Why is this happening and how can I prevent it?

The way I have routes setup is something like this for every new route...

Router.route('/route/:_some_param', {
    name: 'something',
    onBeforeAction: function(){ // Something },
    waitOn: function(){ // Some subscription },
    action: function(){ // Something },
})

I have several routes setup this way. Whenever I moving from page to page Meteor reloads the entire page. However when I stay on one route and just change params, Meteor only reloads what's necessary, which is what I want all the time.

like image 481
Mcope Avatar asked Dec 29 '14 12:12

Mcope


2 Answers

I believe what you are observing is the basis for how Iron Router works. You create a master Template with a {{> yield }} template placeholder, and Iron Router swaps it out for the template specified by that given route. If you choose a different route, the {{> yield }} will now point to the new template, and thus that part of the page will be re-rendered. You can minimize the amount of the page being swapped out by minimizing the scope of your {{> yeild }} in you master template.

For example, in my template I have a header and a footer like this:

<html>
  {{> header }}
  {{> yield }}
  {{> footer }}
</html>

When I navigate the routes, the header and footers don't get updated at all, just the "guts" between them.

like image 86
CodeChimp Avatar answered Oct 09 '22 04:10

CodeChimp


How exactly are you changing pages? Meteor will reload the entire page if you are using traditional anchor tags as an anchor tool.

For example, if you are navigating between templates and are using this sort of structure:

<a href="/pathToTemplate">Let's go to the new template!</a>

Meteor will reload the entire page as you are actually using an anchor tag to tell the browser to change routes. However, if you use this structure:

<a href="{{pathFor 'yourTemplateName'}}">To the new template ahoy!</a>

The link will tell Iron Router to change your template for you and only refresh the code that you have in your {{> yield}} area. To direct your links to the right pages, make sure you put whatever is listed in the name:... field in your router in the 'yourTemplateName' section of the pathFor helper.

In short, the reason you are getting a full-browser refresh is most likely due to the fact that you are using the browser to transition between links instead of using the built-in Meteor and Iron Router helpers to calculate the logic for the transition. There is a lot more you can do with this helper, and if you need further information, I would recommend checking out the Path and Link Template Helpers section on Iron Router's Git page.

If you need only certain part of the page to refresh and the rest to stay the same, then I would refer to CodeChimp's answer as it is sound. If you need various layout templates for various stuff, the Layouts section should help you get nice and dandy with your code and maybe even cause you to crack a smirk like only action heroes unflinchingly walking away from an exploding building do.


Another situation you may find is if you need to use a link to perform an action, but you do not want the browser to hijack the event and re-render the page. In that case, you would set up your HTML like you normally would and then target this element receiving the click event either by its id, class, or tag name and using the following code structure in the javascript file that corresponds to your template. This is useful for submitting forms, which trigger a Meteor method, which does something in the server, and then returns the necessary data (usually to a redirect function) and so on and so forth.

So if you are on the template crazyStuffIsAboutToHappen and you wanted to call a Meteor Method named doCrazyStuff when you click on a link that has an id of #triggerCrazyStuff and then have Meteor redirect your user to the template theHouseThatCrazyStuffBuilt, you would use the following structure.

Template.crazyStuffIsAboutToHappen.events(
  'click #triggerCrazyStuff': (e) ->
    e.preventDefault()  # to stop the browser from hijacking the event

    # -- error handling and pre-submit validation and yadda yadda --        

    Meteor.call('doCrazyStuff', --arguments--, (error, result) ->
      if error
        # handle the error + short-circuit the function. 
        return throwError(error.reason)  

      Router.go('theHouseThatCrazyBuilt, {--args--})
)

And yes, the Template.TEMPLATE_NAME.events area is also very handy for all other JS events out there like MouseEnter and so on and so forth.

Happy Coding!

like image 39
Bottled Smoke Avatar answered Oct 09 '22 05:10

Bottled Smoke