How to make an email web app using Angular

We are going to create an email application using Angular JS. First we’re going to build the front end and wait to add the server portion till the end.

We’re going to learn angular by diving right in and explaining concepts as we go as we need to. Until we need the server portion, we are going to mock that data in right in the code. I think this is not only a good way to learn, it’s a good way to go about building an application.

To start with we need our boilerplate HTML. This HTML will include all the necessary libraries. We are going to use Bootstrap for our look and feel. jQuery for later, and of course Angular.

Here is what that code looks like:

<!DOCTYPE html>
<html>
<head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script  src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js"></script>
    <link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css"/>
    <style type="text/css">
      .container {
          margin-top: 20px;
      }
    </style>
</head>
<body>
    <div class="container">
    </div>
</body>
</html>

I will make all the code available as JSFiddle’s so you can see and play with the code as we go. Here is the JSFiddle for for this code: http://jsfiddle.net/luisperezphd/4bYUV/

Note that the code had to be adjusted to work on JSFiddle. JSFiddle automatically generates the <html>, <head>, <script> and <body> tags for you. So you only have to specify what goes inside thoes tags.

Specifying what JavaScript and CSS to include has to be done using JSFiddle’s options. But ultimately it is equivalent to the code above.

Creating the email list

To start with we are going to focus on functionality related to managing emails, this means we are not going to address things like user sign in, at least not right now.

The first thing we are going to tackle is the email list. From this screen we should be able to see who the email is from, what the subject of the email is, and when we received it.

First we are going to write the HTML for this table, then we are going to use angular to generate it dynamically. Here is the HTML for the static version:

<table class="table table-bordered table-condensed">
    <tbody>
        <tr>
            <td>Guinan</td>
            <td>It's an Earth drink. Prune juice.</td>
            <td>Dec 24</td>
        </tr>
        <tr>
            <td>Beverly Crusher</td>
            <td>Captain always push themselves too hard.</td>
            <td>Dec 23</td>
        </tr>
        <tr>
            <td>Mom</td>
            <td>Don't forget to wear clean underwear today.</td>
            <td>Nov 22</td>
        </tr>
    </tbody>
</table>

The classes on the table are bootstrap classes that make the table look nice. This is what it looks this:

image001
We’re going to take a very incremental step by step approach to build this table using angular in order to introduce several concepts in detail. First we are going to try to use an angular expression to replace one of the pieces of data. Replace Guinan with {{ "Guinan Test" }}. This should cause Guinan Test to be displayed instead of Guinan.

But that’s not what happens. Instead this happens:

image002
This is because AngularJS does not automatically apply itself. You have to tell Angular what portions of the page to apply itself on. You do that by adding the ng-app attribute, you can add that attribute at any level, let’s add it to the container <div> tag and see what happens.

Your html tag should look like this:

<div class="container" ng-app>

When you refresh you should see the value inside the brackets: http://jsfiddle.net/luisperezphd/j226e/

image002
Expressions allow you to embed JavaScript right into your HTML. (Technically it’s not JavaScript – but that’s a topic for another time) In the real world there would be no point in using an expression just to display of a string, I’m doing it here in order to introduce the concept.

Basically angular runs the code inside the double curly brackets and renders the result. If for example you replaced that expression with:

{{ "Guinan" + " " + "Smith" }}

You would get: http://jsfiddle.net/luisperezphd/ARYwd/

image004
If you replaced the expression with:

{{ 10 * 3 }}

You would get: http://jsfiddle.net/luisperezphd/bWhn5/

image005
Again these aren’t real world examples, there would be no point in using an express that multiplies 10 times 3 since we already know the answer. The real fun is when we start using expressions with data.

So let’s continue making this table data driven. Now we already used the ng-app attribute in order for angular to know what portion of the HTML to process. Angular calls these directives. Now we are going to use the ng-init attribute to initialize some data, then update one of the rows to use that data.

We can use this attribute anywhere. I’m going to put it in <tbody> tag. So my <tbody> tag looks like this:

<tbody ng-init="email={from: 'John', subject: 'I love angular', date: 'Jan 1'}">

Now I’m going to update the first row in my table to use that data. From this:

<tr>
    <td>{{ 10 * 3 }}</td>
    <td>It's an Earth drink. Prune juice.</td>
    <td>Dec 24</td>
</tr>

To this:

<tr>
    <td>{{ email.from }}</td>
    <td>{{ email.subject }}</td>
    <td>{{ email.date }}</td>
</tr>

And when I run it I get this: http://jsfiddle.net/luisperezphd/eJ95W/

image006
Alright now we’re playing with power. Now instead of one email let’s do an array of emails, then display one row for each email. To do that we will have to change our “ng-init” so that it creates an array, then use another Angular directive to repeat the HTML row for each email. To do that we use another directive called “ng-repeat”.

So change the ng-init to:

<tbody ng-init="
  emails = [
    { from: 'John', subject: 'I love angular', date: 'Jan 1' },
    { from: 'Jack', subject: 'Angular and I are just friends', date: 'Feb 15' },
    { from: 'Ember', subject: 'I hate you Angular!', date: 'Dec 8' }
  ]
">

Then add the following ng-repeat attribute and value to the <tr> tag:

ng-repeat="email in emails"

So that it looks like this:

<tr ng-repeat="email in emails">

When you run it you should get this: http://jsfiddle.net/luisperezphd/DuyL2/

image007
Now we have a dynamically generated table. The problem is that the code is all in the HTML, what good is that, let’s fix that.

Let’s get the code that initializes the emails array out of the HTML to where it belongs in the JavaScript. To do this we will have to create a special function that Angular calls a controller. Then we will have to use the ng-controller directive to associate that controller with a portion of the HTML – similar to how we used ng-app.

So add the following code:

function EmailController($scope) {
  $scope.emails = [
    { from: 'John', subject: 'I love angular', date: 'Jan 1' },
    { from: 'Jack', subject: 'Angular and I are just friends', date: 'Feb 15' },
    { from: 'Ember', subject: 'I hate you Angular!', date: 'Dec 8' }
  ];
}

Then in your HTML add the ng-controller directive and assign it the value EmailController. You can use this directive on any element, but only that element and child elements can access the emails variable, so it should be assigned to a parent of the <tr> tag. I’m going to add it to the table tag so that it looks like this:

<table ng-controller="EmailController" class="table table-border table-condensed">

If you run it everything should look exactly the same. The only thing that changed is that instead of the emails being initialized inside the HTML, it’s now being initialized inside the controller function: http://jsfiddle.net/luisperezphd/vsUDK/

You noticed the controller function has a parameter called $scope. That’s how data is shared between a controller and the HTML. Any variables created in the $scope by the controller are accessible by the HTML, and vise versa.

For the next post in this series we will add the ability to click on an email and see it’s contents.

How to make an email web app using Angular (Part II)

Note all this code was tested in Google Chrome, it should work across browsers, but if you have any issues with Firefox and IE, let me know and I’ll see what I can do – thanks.

Comments

  1. Gary MacDougall says

    Great introduction to AngularJS. Really explains things clearly and makes it understandable.

    Would be nice to see something on binding data from PHP or .NET.

    But a great introduction, well done!

  2. Ben says

    Please in the future clarify how you are organizing your files, been scanning through the various parts of the series and not seeing a mention of file structure. Also writing your controllers as
    function EmailController($scope) { }
    is not the proper way of doing it, I have seen tutorials use this method, admit its the wrong way, but continue using it. If its bad form why teach it?
    it should be:
    app = module(‘myApp’ []);
    app.controller(‘EmailController’, [‘$scope’, function($scope) { }]);
    I understand this is more wordy, but its the correct way.

      • Luis Perez says

        Thanks for pointing that out Ayush. So that everyone else knows the alternate and new syntax is something like this:

        var module = angular.module(“MyModule”, []);

        module.controller(“EmailController”, function($scope) {
        // your code
        });

  3. Vishal Bhagwat says

    This blog is very very nice to Angular js developer and beginner. All things are explain very well and differentiate very easy way. I am very thankful to you because Now I am clear about the Providers, factory and services with their uses and differentiation. Nice site.

Leave a Reply

Your email address will not be published. Required fields are marked *