Here's an example of our final application. You can see it's pretty straightforward. I'm using iron router for routing, and the root path just shows the title of the first item in the list. If I refresh the page, keep your eyes trained at the top, and you can see the iOS 7 style loading indicator that shows while we're waiting for the data. And then, our template is rendered as usual.
To get us started, let me click over on the NProgress GitHub repository. This lets me get a sense of the project, and I can come over to the SSH URL and copy it so that I can clone the repository locally. I've created a new Meteor project, and I'm showing you the packages that I have. You can see that I've removed auto-publish, and I've added the iron router package. I've also updated my project directory structure a little bit. So, you can see that I have the main app.js file in the root, and I've created a client folder where I'll put all of the client files, like the CSS and any libraries that I might use.
Now let's modify our page route to use the loading indicator. To do that, I'll create a before hook using the before option. In this case, I only have one before hook, so I'll assign this to a function. And the first thing I'll do is subscribe to the items with latency subscription, and assign the result to this handle variable.
Next, we'll check whether or not the handle is ready. This means that we've gotten all of the data, the initial data, from the subscription off the wire. Remember that before hooks are reactive. And so, if this is a reactive data source, and it invalidates the current computation, then this route will be run again, including all of the before hooks.
But you might ask, if this entire function is run again, won't we re-subscribe to the same subscription over and over again, causing, essentially, an infinite loop? The answer is no, because Meteor is smart about how it handles subscriptions. If it sees that we've already subscribed to items with latency, it won't set up a new subscription. It'll just return the existing handle. And that's why this code works.
So, if the handle's not ready, what I'll do is call NProgress, which is the library that we just downloaded. And I'll call this start method. And then I'll stop all downstream hooks from running, including our action function, which renders the page template. And if the data is ready, I'll call NProgress done. And I don't need to do anything else. The rest of my before hooks will run, and my action function will run automatically.
The next thing we need to do is to create a data option on the route. That'll set a global data context that will be used when the templates are rendered to the page. So, over in the HTML file, you can see we're using the title property of the data context. And what we need to do is to set that data context object. So, let's create a data option, and we'll set it to a function that returns the first item in the list.
Now, it turns out that, in iron router, this data function is implemented as a before hook as well. It's just the last one in the list. So, this function won't get called, and this page template won't get rendered, until all of our before hooks have executed. Inside of our before hook, we call stop if the data's not ready. And so, that means the data function won't execute until this subscription is ready.
And now, if we reload the page in the browser, you can see the loading indicator up at the top. And then, when the data comes off the wire, we render the rest of the page, and we show the title at the top.
So, in this video, we looked at how we can integrate a third party user interface library and use it with iron router. We also saw how before hooks are reactive. So, we can call a reactive method that would cause the route to rerun if this current computation is invalidated. We use that knowledge in combination with the third party library to show a loading indicator at the top of the page while we're waiting for data from our subscription. And we also saw how the data function, or the data option, is a downstream before hook itself. So, we can prevent it from running until we're ready by calling the stop method in one of the upstream before hooks.