Logo
ManuelSchoebel

Use Meteor Iron-Router waitOn to load external javascript

You do not always want to load all the javascript you need for your whole application. For example on paypertise we have a rich text editor, but most of the time people are not writing anything (unfortunately ;-) ). But they are browsing for experts or articles, so why would we want to load all the javascript for the rich text editor? Loading external javascript was often quite painful for me, my attempt looked like this:

// Load the external script and when it is done loading, set the reactive session variable
$.getScript(
  editorPath + 'my-rich-text-editor.js',
  function(data, textStatus, jqxhr) {
    Session.set('wysihtml5Loaded', true);
  }
);

In the template i would then do something like this:

<template name="content">
  {{#if javascriptLoaded}}
    {{> textEditor}}
  {{else}}
    <p>loading ...</p>;
  {{/if}}
</template>

Meteors reactivity would render my textEditor once the javascript is loaded. This is just an example, the reality is often even more complicated. Think of multiple asynchronous javascript libraries you would have to load in a exact order, which is no fun at all.

The Iron-Router has a nice functionality, which you can use really nicely to solve this problem. You could either use the before hook, but i like the waitOn function for that more. The idea is to load a library exactly as you subscribe to a publication via the collections. If you subscribe to a publication with Meteor.subscribe('publication') you get back a handle. This handle has a reactive ready function which is called by the Iron-Router. Once everything you are waiting for is ready, the Iron-Router would go on with the before hooks and finally render the template. So what we need is a script loader, that returns an object with a reactive ready function. I implemented one like this:

// this is quite similar to the implementation of Meteor.subscribe
// it simply uses Deps.Dependency to make the handle.ready function reactive
IRLibLoader.load = function(src) {
  var handle, self;
  self = this;
  if (!this._libs[src]) {
    this._libs[src] = {
      src: src,
      ready: false,
      readyDeps: new Deps.Dependency
    };
    $.getScript(src, function() {
      var lib;
      lib = self._libs[src];
      lib.ready = true;
      return lib.readyDeps.changed();
    });
  }
  handle = {
    ready: function() {
      var lib;
      lib = self._libs[src];
      lib.readyDeps.depend();
      return lib.ready;
    }
  };
  return handle;
};


With this you can simply use the Iron-Router to wait on loading external javascript libs like this:

Router.map(
  function() {},
  this.route('myContentEdit', {
    path: '/my/content/:_id',
    layoutTemplate: 'layout',
    waitOn: function() {
      return [
        Meteor.subscribe('content', this.params._id),
        IRLibLoader.load('<code>http://www.paypertise.com/js/text-editor-lib.js'</code>)
      ];
    },
    before: [
      prepareForThis,
      prepareForThat
    ],
    data: function() {
      return Contents.findOne();
    }
  })
);


This way you can easily pre load external javascript with one line.

The script is also in my github repo: https://github.com/DerMambo/wait-on-lib

Also make sure to follow me on twitter :-)

©️ 2025 Digitale Kumpel GmbH. All rights reserved.