Search code examples
javascriptmeteoriron-router

Iron Router: Load js script after template has been rendered


I'm trying to load a javascript file (using IRLibloader) after the Iron Router has rendered the template:

Router.configure({
  layoutTemplate: 'layout',
  loadingTemplate: 'loading',
});

Router.route('/', {
  name: 'landing',
  template: 'landing',
  onBeforeAction: function () {
    var googleAPI = IRLibLoader.load('http://maps.googleapis.com/maps/api/js?libraries=places&sensor=false');
    var fancyInput = IRLibLoader.load('/js/fancyInput.js');
    var geoComplete;
    if(googleAPI.ready()){
      geoComplete = IRLibLoader.load('/js/jquery.geocomplete.min.js');
    }

    if(googleAPI.ready() &&
       fancyInput.ready() &&
       geoComplete.ready()){
      console.log('All ready');
      this.next(); // Render the page when all the libraries are ready

      // Testing this here
      if(Meteor.isClient){
        console.log("Meteor.isClient");
        IRLibLoader.load('/js/landing.js');
        // Set places autocomplete
        Template.landing.rendered = function(){
          $('section :input').val('').fancyInput()[0].focus();
          $('section :input').geocomplete();
          console.log("loading.js ejecutandose (after render)");
        }
      }
    }
  }
});

But when I browse localhost:3000, the layout gets rendered, the googleAPI, fancyInput and geocomplete libraries are loaded too since the 'all ready' message gets printed at console, and landing.js also gets loaded (since it loads the background image and the message 'Meteor.isClient' also gets printed).

But then, the 'landing' template never gets rendered. Its content does not appear, and the console message inside the Template.landing.rendered never gets printed. This is the template.js file:

<template name="landing">
  <img id='logo' src="img/logos/logo.png">
  <div id='content'>
    <section class='input'>
      <div>
        <input type='text' placeholder='Type text here'>
      </div>
    </section>
  </div>
</template>

I also tried loading landing.js with onAfterAction, which seems to happen before the onBeforeAction according to the Firebug console. How strange!

I can't understand why the template is not being loaded, since no error appears at meteor console. Any idea?

EDIT: it does work if I remove the layout, which looks like this:

<template name="layout">
  <head>
    <title>Welcome to my app</title>
  </head>
</template>

What's wrong with this layout?


Solution

  • So, I think you might be overthinking this a little. Why not use existing packages for these libraries? Aside from being significantly easier to use, some of that 3rd party code would get minified into the main app js file instead of making additional HTTP requests to download them.

    For example, dburles:google-maps gets you the Google Maps API and extra libs of your choice (with the option to only load on specific routes) and jeremy:geocomplete gets you Geocomplete (which automatically installs that maps package as a dependency). See the jeremy:geocomplete README for implementation.

    As for Fancy Input, why not create a simple Meteor package wrapper for that so you can just meteor add fancy-input?

    Also, your Template.landing.rendered callback should not be in an onBeforeAction. Ideally, it should be in its own file with other code for the landing template.