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:
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:
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/
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/
If you replaced the expression with:
{{ 10 * 3 }}
You would get: http://jsfiddle.net/luisperezphd/bWhn5/
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/
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/
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.
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!
Chankey Pathak says
Starting to learn Angular, and the journey is starting from this article. Very well explained, thanks!
Aryan says
Very Well Explained
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.
ayush khanduri says
function EmailController($scope) { }
it is deprecated now …. you can not use the use it in the newer versions of angular ….
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
});
server security says
This site was… how do you say it? Relevant!! Finally I have found something that helped me. Cheers!
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.
Sumita says
Nicely explained. Easy to understand. I love it the way you presented.
Thanks