Introduction

I started using AngularJS over 3 years ago when it was new and relatively unknown. Since then AngularJS has become one of the most popular JavaScript frameworks and for good reason. The AngularJS team have done superb work and are very dedicated to ensuring AngularJS is the best it can be.

This AngularJS tutorial will be using version 1.3.4 and will cover just the basics and follow the best practices recommended by Google and by me through my own experience.

Setup

To get started create a folder called angularjs-tutorial and create the following files copying the directory structure below.

- angularjs-tutorial
    | - main.ctrl.js
    | - app.js
    | - index.html

Open index.html and add the following simple HTML to create a basic web page that includes AngularJS and Twitter Bootstrap from a CDN. We are going to use Twitter Bootstrap as the CSS framework so its easy for us to quickly create the layout and focus more on the AngularJS. If you would like to know more about Twitter Bootstrap please check out my Twitter Bootstrap Tutorial.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>AngularJS Tutorial</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script>
    <script src="app.js"></script>
    <script src="main.ctrl.js"></script>
</head>
<body>

</body>
</html>

This HTML document also includes app.js and main.ctrl.js which you have just created.

Angularfy your web page

Within our app.js file we need to instantiate an AngularJS module which we will use for our app. Copy the follow code into app.js

angular.module('app', []);

The angular.module() function acts as a setter and getter for angular modules. The first argument is the name of the module where we chose app, for the second we provided an array. If an array is provided then angular will create the app module as opposed to retrieving it which you’ll see later when we create our controller.

Info

In more complex applications you will provide an array of module dependencies as opposed to an empty array as with this example.

Now we need to tell angular where we want to use this module, open up index.html and add ng-app='app' to the <body> tag as shown below.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>AngularJS Tutorial</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script>
</head>
<body ng-app="app">

</body>
</html>

This tells angular that everything within the DOM under body is part of our AngularJS application called app.

The controller

AngularJS provides a loose MVC structure more accurately described as MVVM. The controller is where your business logic should be handled, essentially the controller ‘controls’ the data and provides it to the view for display. To declare our main controller open up main.ctrl.js and add the following JavaScript code.

angular.module('app').controller("MainController", function(){
    var vm = this;
});

In the code above we first retrieve the app module we created early and then use the controller function to instantiate a new controller. The controller function takes two parameters. The first is the controller name and the second is a function where we will place our controlling code.

Before we can use the controller we need to tell angular which part of our HTML document this controller has governance over. You can have many controllers per document and many controllers governing the same section of a document, you can even have nested controllers. In our very simple example we are going to have a single controller governing the entire page. We will use the controllerAs syntax to declare this (more on this later), open index.html and add the following to the body tag.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>AngularJS Tutorial</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script>
</head>
<body ng-app="app" ng-controller="MainController as main">

</body>
</html>

Understanding scope

Traditionally you would inject $scope into the controller and assign all controller variables to the scope object which will then make them accessible within the view. However, the better approach and recommended by the AngularJS team is the controllerAs syntax. This provides a more semantic approach to declaring controllers within your HTML and also prevents issues such as scope bleed when multiple-nested controllers are present.

We capture the controller instance into the vm variable which stands for ViewModel as recommended by John Papa’s style guide. We will then assign all controller variables that we need access to within the view to this object so angular can work its magic, such as two-way data binding.

To understand the scope lets declare a simple variable called title which will hold some title text we want to display within our web page. Open main.ctrl.js and add the following.

angular.module('app').controller("MainController", function(){
    var vm = this;
    vm.title = 'AngularJS Tutorial Example';
});

To display this text within our web page we use the following syntax.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>AngularJS Tutorial</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script>
</head>
<body ng-app="app" ng-controller="MainController as main">
    <div class="container">
        <h1>{{main.title}}</h1>
    </div>
</body>
</html>

In the above example we are displaying the title text inside a h1 tag using a set of curly braces so that angular knows that this is a variable. We access the controllers scope by prefixing the variable with main matching our ControllerAs definition. Now imagine that we had multiple controllers in the same document and you were referencing multiple variables using the traditional method where you would simple do {{title}}. It would be very difficult to see which scope the variables were present in. Additionally it would also be easy to accidentally have multiple variables with the same name (i.e scope bleed).

If you open index.html within a web page you should see the title text output as a header on a very boring web page.

See the Pen EaVWWy by Leon Revill (@RevillWeb) on CodePen.

Understanding binding

Two-way data binding is one of the main selling points of AngularJS so lets take a look what its all about. Within main.ctrl.js add another variable called searchInput as shown below.

angular.module('app').controller("MainController", function(){
    var vm = this;
    vm.title = 'AngularJS Tutorial Example';
    vm.searchInput = '';
});

Open index.html and add a very simple search input using the following code.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>AngularJS Tutorial</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script>
    <script src="app.js"></script>
    <script src="main.ctrl.js"></script>
</head>
<body ng-app="app" ng-controller="MainController as main">
<div class="container">
    <h1>{{main.title}}</h1>
    <div class="input-group">
        <span class="input-group-addon">
            <span class="glyphicon glyphicon-search"></span>
        </span>
        <input type="text" class="form-control" ng-model="main.searchInput">
    </div>
    <p>{{main.searchInput}}</p>
</div>
</body>
</html>

In addition to adding a search input we have used the curly braces again to output the searchInput variable. On the text input we have added the ng-model directive and specified the searchInput variable from our main controller. This input is now bound to this variable making the inputs value available from within the controller code and also from anywhere within the HTML document that is governed by the controller. Now if you open index.html in a browser and type within the search box you should instantly see the search input value printed underneath as you type. Have a go using the live preview below.

See the Pen QwjpdP by Leon Revill (@RevillWeb) on CodePen.

Using ngRepeat

AngularJS provides a wide range of built in directives for you to help you perform common tasks. The ngRepeat directive allows you to iterative through items and display them on the page. Let’s create an array of objects we can iterate through. Update main.ctrl.js to have the following array.

angular.module('app').controller("MainController", function(){
    var vm = this;
    vm.title = 'AngularJS Tutorial Example';
    vm.searchInput = '';
    vm.shows = [
        {
            title: 'Game of Thrones',
            year: 2011,
            favorite: true
        },
        {
            title: 'Walking Dead',
            year: 2010,
            favorite: false
        },
        {
            title: 'Firefly',
            year: 2002,
            favorite: true
        },
        {
            title: 'Banshee',
            year: 2013,
            favorite: true
        },
        {
            title: 'Greys Anatomy',
            year: 2005,
            favorite: false
        }
    ];
});
Info

In a real-world scenario data such as this would probably be loaded via an API using a service to interact and store the data locally.

Now we have an array we can use the ngRepeat directive to loop through each TV show and create an unordered list within our web page. Open index.html and add the following code.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>AngularJS Tutorial</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script>
    <script src="app.js"></script>
    <script src="main.ctrl.js"></script>
</head>
<body ng-app="app" ng-controller="MainController as main">
<div class="container">
    <h1>{{main.title}}</h1>
    <div class="input-group">
        <span class="input-group-addon">
            <span class="glyphicon glyphicon-search"></span>
        </span>
        <input type="text" class="form-control" ng-model="main.searchInput">
    </div>
    <h3>A list of TV shows</h3>
    <ul class="list-group">
        <li class="list-group-item" ng-repeat="show in main.shows">{{show.title}} <span class="badge">{{show.year}}</span></li>
    </ul>
</div>
</body>
</html>

In this example ngRepeat will copy the list item element for each item in our shows array. We can then access properties of each show using {{show.[property]}} to display them within the list element.

Hiding and showing elements

Another set of directives that AngularJS provides allow you to easily hide and show DOM elements based on criteria or an expression. These directives are ngHide, ngShow, ngSwitch & ngIf. Even though these directives provide a similar result they are useful in different situations. The ngSwitch directive is useful when you have a case like situation, such as a radio button toggle. ngHide, ngShow and ngIf are very similar except with a fundamental difference. ngIf will remove the affected element from the DOM where ngHide and ngShow will essentially add a display: none; to it hiding it from view.

Therefore ngIf should be used where possible as this will save the browsers memory due to a decluttered DOM. ngHide and ngShow are particularly useful when the items are animated as the additional overhead of adding the element back to the DOM with ngIf can often affect the animations.

For our simple example we would like to add a star next to each TV show in the list only if the show is marked as a favorite. Update index.html to use ngIf as follows.

<h3>A list of TV shows</h3>
<ul class="list-group">
    <li class="list-group-item" ng-repeat="show in main.shows"><span class="glyphicon glyphicon-star" ng-if="show.favorite"></span> {{show.title}} <span class="badge">{{show.year}}</span></li>
</ul>

This simply added the star icon to the DOM when the show.favorite property is equal to true. It’s worth mentioning that expressions can be used here so something like show.favorite == true or show.favorite != false would also work.

Using filters with ngRepeat

AngularJS provides the ability to easily filter repeated content. Let’s use the search input we created earlier to allow users to filter the TV show list.

<h3>A list of TV shows</h3>
<ul class="list-group">
    <li class="list-group-item" ng-repeat="show in main.shows | filter:main.searchInput"><span class="glyphicon glyphicon-star" ng-if="show.favorite"></span> {{show.title}} <span class="badge">{{show.year}}</span></li>
</ul>

It’s that easy! Imagine trying to do something like that with jQuery. Have a play around with this implementation below.

See the Pen AngularJS Filter Example by Leon Revill (@RevillWeb) on CodePen.

Let’s make things a little more complicated and add the option to change the order of the list items. Update main.ctrl.js with another set of objects specifying the order types available.

vm.orders = [
    {
        id: 1,
        title: 'Year Ascending',
        key: 'year',
        reverse: false
    },
    {
        id: 2,
        title: 'Year Descending',
        key: 'year',
        reverse: true
    },
    {
        id: 3,
        title: 'Title Ascending',
        key: 'title',
        reverse: false
    },
    {
        id: 4,
        title: 'Title Descending',
        key: 'title',
        reverse: true
    }
];
vm.order = vm.orders[0];

Now add a select menu to index.html so the user is able to choose the list order and add an additional filter to the ngRepeat we added earlier.

<body ng-app="app" ng-controller="MainController as main">
<div class="container">
    <h1>{{main.title}}</h1>
    <div class="input-group">
        <span class="input-group-addon">
            <span class="glyphicon glyphicon-search"></span>
        </span>
        <input type="text" class="form-control" ng-model="main.searchInput">
    </div>
    <h3>A list of TV shows</h3>
    <ul class="list-group">
        <li class="list-group-item" ng-repeat="show in main.shows | filter:main.searchInput | orderBy:main.order.key:main.order.reverse"><span class="glyphicon glyphicon-star" ng-if="show.favorite"></span> {{show.title}} <span class="badge">{{show.year}}</span></li>
    </ul>
    <select class="form-control pull-right" ng-model="main.order" ng-options="order as order.title for order in main.orders"></select>
</div>
</body>

Above we have added an orderBy filter to the ngRepeat specifying which key of the show object we want to order by, in this case title. We then specified the direction of the order which is stored within the orders objects as reverse. To populate the select menu we use the ngOptions directive which you can read more about here.

See it in action below by changing the selected value in the select menu.

See the Pen AngularJS order by example by Leon Revill (@RevillWeb) on CodePen.

Form validation

Collecting data from a user makes up a large part of web applications. AngularJS makes it easy to validate form data before it is used by your application. In this simple example we will create a form allowing the user to add a new TV show to the list. Open index.html and add the following HTML to create a simple form.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>AngularJS Tutorial</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script>
    <script src="app.js"></script>
    <script src="main.ctrl.js"></script>
</head>
<body ng-app="app" ng-controller="MainController as main">
<div class="container">
    <h1>{{main.title}}</h1>
    <div class="input-group">
        <span class="input-group-addon">
            <span class="glyphicon glyphicon-search"></span>
        </span>
        <input type="text" class="form-control" ng-model="main.searchInput">
    </div>
    <h3>A list of TV shows</h3>
    <ul class="list-group">
        <li class="list-group-item" ng-repeat="show in main.shows | filter:main.searchInput | orderBy:main.order.key:main.order.reverse"><span class="glyphicon glyphicon-star" ng-if="show.favorite"></span> {{show.title}} <span class="badge">{{show.year}}</span></li>
    </ul>
    <select class="form-control pull-right" ng-model="main.order" ng-options="order as order.title for order in main.orders"></select>
    <div class="clearfix"></div>
    <h3>Add a new TV Show</h3>
    <form name="main.addForm" class="form">
        <div class="form-group">
            <label>Title</label>
            <input type="text" class="form-control" ng-model="main.new.title" required />
        </div>
        <div class="form-group">
            <label>Year</label>
            <input type="number" min="1900" max="2030" class="form-control" ng-model="main.new.year" required />
        </div>
        <div class="row">
            <div class="col-xs-6">
                <label>Favorite: <input type="checkbox" ng-model="main.new.favorite" /></label>
            </div>
            <div class="col-xs-6">
                <button class="btn btn-success pull-right"><span class="glyphicon glyphicon-plus-sign"></span> Add</button>
            </div>
        </div>
    </form>
</div>
</body>
</html>

This simple form will allow the user to enter a show title, year and specify if it is a favorite. On the title and year fields we have added a required attributed marking this field as required. Additionally we have specified the field type for the year input as number and added the additional min and max properties. AngularJS provides out of the box form validation and will automatically provide feedback to the user when they click the add button. If the user has not entered a value in either of the required fields they will be prompted with an error message. Also, if the user has not entered a number between 1900 and 2030 they will be instructed to do so. Try it yourself using the pen below.

See the Pen AngularJS simple form validation by Leon Revill (@RevillWeb) on CodePen.

Read more about forms with AngularJS here.

Responding to simple events

The final part of this AngularJS tutorial will show you how events are used within the framework. Events have always been an important part in JavaScript frameworks and libraries and it is no different here, even with Angular’s two-way data binding.

The form we just created is useless if the user is unable to actually submit the data and add it to the list of shows. Add the following code to the bottom of MainController.

vm.new = {};
vm.addShow = function() {
    vm.shows.push(vm.new);
    vm.new = {};
};

The above code declares an object called new which the form uses to store its input values denoted by the ngModel value (i.e. ng-model="main.new.year"). Also a function addShow is created which pushes the new object into the shows array and adds it to the list within the view.

AngularJS provides various event directives such as ngClick, ngChange, ngFocus, etc. that we can use to react upon. In our simple example we will use the ngSubmit directive to trigger the addShow function when the form is successfully submitted. Open index.html and amened your form declaration to include this directive as shown below.

<form name="main.addForm" class="form" ng-submit="main.addShow()">

Now, when the form passes validation and the user clicks the add button this addShow function will get called, adding the new show to the list. Have a go!

See the Pen AngularJS ngSubmit example by Leon Revill (@RevillWeb) on CodePen.

This is an extremely simple example of one in many event directives AngularJS provides, head over to the documentation to learn more.

Conclusion

In this quick tutorial you should now have a good working understand of many AngularJS concepts which will allow you to build simple single page applications. AngularJS offers so much more than I can show you in 30 minutes, if you liked this tutorial then please subscribe below to receive updates regarding up coming advanced AngularJS tutorials.