Rapid Prototyping with Meteor.js
This tutorial assumes that you have Node.js and Meteor installed.
Step 1: Create a meteor app #
Creating a new app in Meteor is very easy:
$ meteor create chat
To start Meteor we cd into the newly created directory and simply type meteor
:
$ cd chat
$ meteor
If we now go to http://localhost:3000/ in our browser, we are greeted by the following welcome message from Meteor.
If we inspect the contents of the chat directory with the ls
command, we see that Meteor has created one directory .meteor for us and three files: chat.css, chat.html and chat.js
The .metor directory is used for internal Meteor files, and we need not concerne ourselves with this directory now.
The css file is where we put any stylesheet information. This file is empty for now. The html file has the necessary HTML to display the welcome message:
<head>
<title>chat</title>
</head>
<body>
{{> hello}}
</body>
<template name="hello">
<h1>Hello World!</h1>
{{greeting}}
<input type="button" value="Click" />
</template>
Apart from the familiar HTML the file contains Handlebars expressions, i.e. {{> hello}}
. Handlebars is Meteor’s default templating system.
The application logic resides in chat.js. Let’s inspect the file:
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to chat.";
};
Template.hello.events({
'click input' : function () {
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
As we can see, the file includes both client and server code. In a more full fledged Meteor app you would put client and server code into their respective directories — code in the client directory will only run on the client and code in the server directory will only run on the surver.
In this simple application we will keep the code in one single file. So what’s going on here?
First, Meteor checks what code to be run, i.e. client or server. Nothing much goes on in the server code.
The client code is more interesting. First, the Handlebars template greetings is initialized with a welcome message. Second, Meteor is set up to listen for a click event from the button on the greeting page. As you can see, the message “You pressed the button” will be printed to the JavaScript console in case of a click.
Let’s modify this behaviour:
Template.hello.events({
'click input' : function () {
alert("You pressed the button");
}
});
Clicking the button should now result in an alert box.
Notice that Meteor hot-pushes changes to files — you don’t have to restart the server or even refresh the browser to see the effects of the change you made.
Step 2: Create User Accounts and Login Functionality #
Next we want to add the ability to log into our app. For this we’ll make use of some of the packages that comes bundeled with Meteor. To see the list of available packages, type:
$ meteor list
At the top of the list we see several packages that begin with the name account. We’ll use two of them to implement our login system:
$ meteor add accounts-password
$ meteor add accounts-ui
We can remove much of the code in the chat.js file. Notice that we add a simple configuration setting to the Accounts.ui. This let’s us sign up with only a username, so we don’t have to provide an email address:
if (Meteor.isClient) {
Accounts.ui.config({
passwordSignupFields: "USERNAME_ONLY"
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
We then change the chat.html file to provide the login functionality:
<head>
<title>chat</title>
</head>
<body>
{{> hello}}
</body>
<template name="hello">
<h1>Welcome to the Chat App!</h1>
{{loginButtons}}
</template>
The simple Handlebars expression {{loginButtons}} is all we need to get the login functionality. We can now create an account and sign in and out. It doesn’t get much more easy than that.
Step 3: Add Chat #
Now, let’s make it possible for logged in users to type in chat messages as well as see messages typed by others:
<head>
<title>chat</title>
</head>
<body>
<h1>Welcome to the Chat App!</h1>
{{loginButtons}}
<br>
{{#if currentUser}}
{{> addMessage}}
{{> listMessages}}
{{/if}}
</body>
<template name="addMessage">
<textarea rows="1" name="messageText" id="messageText" placeholder="Type your message here..."></textarea>
<br/>
<input type="button" class="add-message" value="Send Message"/>
<br>
</template>
<template name="listMessages">
{{#each messages}}
<strong>{{name}}:</strong> {{message}}<br>
{{/each}}
</template>
Here we add a little bit of Handlebars logic with the {{#if currentUser}}
statement. currentUser
is true if the a user is logged in. If so, we render the addMessage
and messages
templates that we have defined below the HTML body.
We now need to provide the logic for saving and retrieving messages. First we’ll use Meteor’s Collection class, which let’s us declare and manipulate Mongo database collections.
Next we need to add messages to this collection, and finally we need to retrieve them. This is the resulting chat.js file:
Messages = new Meteor.Collection("messages");
if (Meteor.isClient) {
Accounts.ui.config({
passwordSignupFields: "USERNAME_ONLY"
});
Template.addMessage.events({
'click input.add-message' : function(event){
event.preventDefault();
var messageText = document.getElementById("messageText").value;
Messages.insert({
name: Meteor.user().username,
message: messageText,
time: Date.now(),
});
document.getElementById("messageText").value = "";
}
});
Template.listMessages.messages = function () {
return Messages.find({}, { sort: { time: -1 }});
}
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
Template.addMessage.events
listens for a click from the message submit button and inserts the message into the Messages collection.
Template.listMessages.messages
retreives the messages from the collection and sorts them by submission time before returning them.
Notice that Meteor automatically propagates our new messages to the server and on the other clients. Try it by opening a new browser and logging in as another user.
That’s it. We now have a functioning albeit basic chat app.