Next lesson playing in 5 seconds

Cancel
  • Overview
  • Transcript

4.1 Waiting for Data

Now that we've completed the page that displays the list of users, we're ready to move onto the next page which will display the list of games that the user is currently involved in. However, we're gonna do something a little bit different this time. So we'll start by adding a games route to our router. So if we open up our router.js file, let's add a new record here so we'll say flow router .route and this will be to /games. And in our options objects, we'll set the name to games. And, once again, I'm just gonna copy our action function from one of our other routes. And, let's see, we want to render the layout. But instead, the child is going to be games. Okay, so this means we're going to need a games template. So just like we did with users, I'm going to create a folder for the template and its accompanying JavaScript. So let's go ahead and make a directory client/games. So now I'll create a new file, client/games. And we're gonna call it games.html, and in here let's create a template, and we'll give it the name games. Now we're going to something a little bit different with this games template. I wanna show you a meteor technique that can really improve your web applications. And to do that, of course, I'll need to create the JavaScript file to go along with this. So we'll have client/games/games.js. And just like we did in our users template, let's make our subscriptions when this template is created. So we'll say Template.games.onCreated. And we'll have a function here. And in this function we can say this.subscribe. And we will subscribe to users, and we'll also say this.subscribe('games'). Now at this point we don't actually have a game subscription so we have to create that on the server. So if we go to our server/main.js file, let's do another Meteor publish. And this time we'll publish games. And in this case we want to return our games collection, right? So we're gonna say, games.find, but we don't want to return all the games. We only want to return games that belong to the currently logged in user. Now from within a publish function, we can get the id of the logged in user by saying this.userId. So we're going to make use of that and we wanna find all of the games where this userId is in the game record. Now there are two fields where the userId is going to be kept. Either the user is playing black in which case the b field will be this.userId or they are playing white in which case it will be the w field that will have this.userId. So what we wanna do is use a Mongo or query. So we'll say $or: and we will pass this in array. And this is going to return all of the records where one of the queries inside of this array is true. So let's see, we're gonna have two queries here and we can say or where b: this.userId or where w: this.userid. Where one of those things is true, we will return all of those games. All right, so now we're publishing the right set of games. And in our games template here, we are successfully receiving that set of games. However the way meteor works is that it will immediately try to render our games template as soon as we navigate onto this page and the template is being displayed. Now that's pretty much the exact same time as we are subscribing to our users in games. And so we won't actually have that game's data just yet because meteor of course will have to make a request to the server which will then have to return the games. So it's possible that we could try and render this template, before we actually have the data that we need. Now because we're using the templates own subscribe method, there's another method the templates have that works in conjunction with subscribe that we now have access to, and this is a method we use from within our templates. And we can use it from within an if block and the method is Template.subscriptionsReady. And this will return true, if our subscriptions are ready to be used. So we can just use this if statement like this and that way if meteor tries to render the template before we actually have the data. Well then nothing will actually render just yet because there's no data to render. Now we may want to render a waiting message. So why don't we go ahead and install a spinner package. I'm going to head back to our terminal here and we're going to do meteor add. And the package we want to add is sacha:spin and I hope I'm pronouncing that name right. This package will just give us a handy little spinner template. That will show a spinner as kind of like a waiting sign while our data is loading. Now unfortunately, because we're working on a localhost here, we probably won't ever get to see this. However, if we were going to deploy this application, this spinner would give us a nice bit of user experience. And we can use that just by saying spinner. So basically what we've just done here, is we've said, if the template subscriptions are ready, well then we're gonna go ahead and put our actual template content in here. However if we're still waiting for data from the server, then just go ahead and show a spinner until that data is ready. Now while we're creating some framework for this template, there's another problem that we might wanna deal with. If someone comes to our application, and they haven't logged in yet. They'll be able to view our list of users, and that's okay because they won't see the add or remove button. However, if they're not logged in, then there's not really much we can show them on the game's page, because someone who is not logged in doesn't have any games. So, we're going to require them to log in before they can actually see the content of this page. And to do this, we're going to create a block helper function. Now, we could just build this right into the game's template, but by making this a helper template, it allows us to reuse it in other places if we need to. So we have a client templates folder and in here, I'm going to create a require login.html file. And let's create a new template here and the name of this template is going to be requireLogin. And this is going to be really, really simple. We can just say, if currentUser. Remember if there is a current user logged in, that will return the user object. Otherwise it will return null, so our if statement will not pass. And if there is a current user, that's fine. Let's just render template content.block. This is a block template because we can actually create opening and closing tags for require login and anything that we put inside of those will be put in the place of Template.contentBlock. Now if there is no current user, then let's just add an h2 element here and we'll just say, Please sign in above. And so now to use this template, we can come over to our games.html file. And in the games template, let's wrap everything in double curly brace. #requireLogin. Just like that, and at the bottom we will do the closing requireLogin. So now what happens is when the user comes to this template, the first thing we check to see is are they logged in. And if they're not, we'll ask them to login. If they are logged in, we'll check to see that we have data to display. And if we do, we'll display it. Otherwise we'll show them a spinner and when that data arrives we'll re-render the template because subscriptionsReady is a reactive data function. So when that value changes, the template is automatically re-rendered. Okay, so for now why don't I just put an H2 in here, and we'll just say games. And let's see what happens when we load this up in the browser. Okay, so if we come to the browser and go to find my friends, we can see that we have a list of friends here, we can go back to the homepage. Now if I click plays of chess, you can see we have this Games header here. Which is what we expected. If i sign out, notice that it changes to, please sign in above, and I can go ahead and sign in, and it changes back to games. That's excellent. All right. And you know while we're at it, why don't we put some links for these two pages into our navigation bar here. So, I'm gonna go ahead and open up client/templates/layout. And then right here where we have this link in the first unordered list. I'm gonna copy that and duplicate it twice and first I'm going to get rid of the class navbar brand. The first link will go to users and we'll just say, find friends. And the second link will go to /games and we'll say Play Chess. So now if we come back and refresh our browser, let's see. Find Friends takes us to the users list, Play Chess takes us to the game list. Excellent. Okay, so our games page is now ready for us to actually build in some content. In the next lesson, we'll look at creating the form that allows us to start a new game.

Back to the top