I've written before about writing an AngularJS app with Express, but this time I'll be writing about how to integrate Socket.IO to add real-time features to an AngularJS application. In this tutorial, I'm going to walk through writing a instant messaging app. This builds upon my earlier tutorial (using a similar node.js stack on the server), so I recommend checking that out first if you haven't.

Once you have the seed, you need to grab a few dependencies with npm. Open a terminal to the directory with the seed, and run:

λ → npm install

With these dependencies installed, you can run the skeleton app:

λ → node app.js

and see it in your browser at http://localhost:3000 to ensure that the seed is working as expected.

Deciding on App Features

There are more than a few different ways to write a chat application, so let's describe the minimal features that ours will have. There will be just one chat room that all users will belong to. Users can choose and change their name, but the names must be unique. The server will enforce this uniqueness and announce when users change their names. The client should expose a list of messages, and a list of users currently in the chat room.

A Simple Front End

With this specification, we can make a simple front end with Jade that provies the necessary UI elements. Open views/index.jade and add this inside of block body:

Interacting with Socket.IO

Although Socket.IO exposes an io variable on the window, it's better to encapsulate it in AngularJS's Dependency Injection system. So, we'll start by writing a service to wrap the socket object returned by Socket.IO. This is awesome, because it will make it much easier to test our controller later. Open public/js/services.js and replace the contents with:

Notice that at we wrap each socket callback in $scope.$apply. This tells AngularJS that it needs to check the state of the application and update the templates if there was a change after running the callback passed to it. Internally, $http works in the same way; after some XHR returns, it calls $scope.$apply, so that AngularJS can update its views accordingly.

Note that this service doesn't wrap the entire Socket.IO API (that's left as an exercise for the reader ;P ). However, it covers the methods used in this tutorial, and should point you in the right direction if you want to expand on it. I may revisit writing a complete wrapper, but that's beyond the scope of this article.

Now, within our controller, we can ask for the socket object, much like we would with $http:

functionAppCtrl($scope, socket) {/* Controller logic */
}

Inside the controller, let's add logic for sending and receiving messages. Open js/public/controllers.js and replace the contents with the following:

And with that, the application should be complete. Try it out by running node app.js. The application should update in real-time, thanks to Socket.IO.

Conclusion

There's a lot more you could add to this instant messaging app. For instance, you can submit empty messages. You could use ng-valid to prevent this on the client side, and a check on the server. Maybe the server could keep a recent history of messages for the benefit of new users joining the app.

Writing AngularJS apps that make use of other libraries is easy once you understand how to wrap them in a service and notify Angular that a model has changed. Next I plan to cover using AngularJS with D3.js, the popular visualization library.