Real-time eye candy with AngularJS

FITC Toronto, December 2013

By Matias Niemelä

@yearofmoo

http://www.yearofmoo.com

Eight major AngularJS articles.

Great resource to learn about AngularJS.

Link to Slides

yom.nu/fitc-slides-dec-2013

I am here to ...

Talk about Real-time web applications

How to integrate Real-time features

Explain that AngularJS is the right tool for the job

Show how to master the UI of your real-time application

Briefly talk about testing and maintainable code

AngularJS

An amazing framework for building dynamic web interfaces

Runs in the browser not on the server

But your backend can be anything

Does this ring a bell?

Let's do a quick example

Web(sites|apps) & Real-time Apps?

Traditional websites -- little or no AJAX here

AJAX web applications -- SPA applications

Fully Real-time applications -- WebSockets

But what about a mixture of all three?

As the web gets better...

Content renders on screen faster and seamlessly

Easier and easier to make websites dynamic

More control over what changes and what stays

But...

As a result...

More AJAX === a more instantaneous expectation

The gap between expired and instant becomes smaller and smaller

users will eventually expect applications to be fully real-time

So webapps should not require the user to refresh the page anymore

Does the page update when the user walks away from the screen?

Why do we really need a refresh button?

So how does this work?

Hook into the hashbang/pushState URL change

Figure out what page to download

Update the body of the page

Perform a fancy animation

AngularJS FTW!

The best of both worlds (hybrid web applications)

Use AJAX from the start (standard SPA application)

Then apply real-time effects as you go?

What is the first problem that comes to mind?

Lets try and make something

Lets try and use pusher.js to update a page

Problems you can run into

Update collisions between AJAX data and Real-time data

Dependency issues

Disorganized Code

Problematic or absence of testing ... How do we test this?

So what are these hybrid applications?

Standard SPA/Traditional websites primarily

Uses WebSockets (a real-time connection) to enhance the experience

Gracefully degrade for older browsers

Kind of like a mobile first approach to making real-time applications

You don’t need to make the entire website using a real-time backend

Great examples of hybrid applications

Github (PR pages)

Asana (tasks)

Facebook (chat)

Our demo application...

Why AngularJS for a real-time web application?

The scoping system allows for an easy way to update data

Directives & Expressions can update the DOM as the data changes

Animations can make it look nice

AngularJS can work with a non-angular application

How does this work?

Bindings, directives and expressions listen on the scope

The scope is your in-memory database

Place AJAX and/or real-time data into the scope

The page updates, renders and animates

Let's use AngularJS instead on our previous example

Lets try and use pusher.js

With angular.js

To make a Real-time application

Types of real-time connections

Native WebSockets

Socket.io (code wrapper)

Pusher.js (streaming service)

Firebase (full backend service)

What code are we using?

Grunt, NPM + Bower

Karma with Jasmine (unit testing)

Protractor (end to end testing)

AngularJS 1.2 (ngRoute + ngAnimate)

Pusher.js

What about the backend?

A simple Rails app to manage the admin

JBuilder for the API

RailsAdmin for a pre-made admin

Whenever the model changes, upload to pusher

Let's Explore the application

Simple crud application that uses AngularJS and an API

Routes, pages, views and styles

Users, comments, images and more

Nice, clean JavaScript code

Let's make it "Real-time"

Real-time effects update the page as things change

The user instantly knows when something has changed or been added

Animations enhance the experience...

From Pusher to AngularJS

Just add the data to the scope


$http.get(API_PATH + '/users?limit=18')
  .success(function(data) {
    $scope.users = data.users;
  });
userChannel.bind('create', function(user) {
  $scope.$apply(function() {
    $scope.users.unshift(user);
  });
});
userChannel.bind('destroy', function(user) {
  $scope.$apply(function() {
    $scope.users = modifyCollection($scope.users, user, 'destroy');
  });
});
          

Then display the contents as normal

The template doesn't care where the data comes from


Animations in AngularJS

Use angular-animate.js with 1.2

Include the ngAnimate module

Supports CSS3 Transitions / Keyframe animations

Supports JS callback animations

Let's examine some animations in the app

CSS Code

Include ngAnimate to make this work


.animate-listing {
  transition:0.2s linear all;
}

.animate-listing.ng-enter { /* enter from */ }
.animate-listing.ng-enter.ng-enter-active { /* enter to */ }

.animate-listing.ng-leave { /* leave from */ }
.animate-listing.ng-leave.ng-leave-active { /* leave to */ }

Staggering Animations

Brand new feature with 1.2


.animate-listing.ng-leave-stagger,
.animate-listing.ng-enter-stagger {
  /* sets the delay between each item */
  transition-delay:0.05s;
  -webkit-transition-delay:0.05s;

  /* these need to be placed here as well */
  transition-duration:0;
  -webkit-transition-duration:0;
}

Let's do some unit testing

Jasmine tests the JavaScript code

angular-mocks.js provides mocking support

Karma runs the tests on all browsers

Let's do some integration testing

What is Protractor?

How does it work?

What can you test with it?

Let's test it out

Thank you!

Thank you for making this possible

@yearofmoo

Feel free to contact me via [email protected]

Code: yom.nu/fitc-yom-demo