You'll notice that there are code checks included throughout this guide. We recommend looking at them and making sure you understand the core concepts, but don't worry about replicating them just yet. Save that for the last section, which has a code-along video included. Use the video as a guide when coding up your own Gmail clone!

Note: This guide is open to the public. You can view the source code on GitHub where you'll find a sample app to folow along.

View: The HTML and presentation of the data. That's what the user sees and interacts with.

Controller: The connector that makes all the different pieces of our application work together.

The MVC pattern is a proven approach to organizing application code that's been refined over many years.

Fun fact: Ruby on Rails is an MVC framework for the Ruby programming language.

Angular likes to use MV* techniques, where the * stands for 'whatever' (often refered to as MVW). In other words, the Controller part is different to usual, but this is beside the point, lets get something working.

Welcome to Thinkful's AngularJS Tutorial! Click here to share what you'd like to learn about next :)

Adding Angular to your page

Angular comes as a single .js file that needs to be included at the bottom of your HTML page. I'd advise putting it there rather than in the <head> for better document rendering.

Note: You need to add the AngularJS library before we can get any of the Angular goodies working and see what they do. Let's do just that!

For this app we're going to use version 1.2.22, which at the moment of writing this is the most recent. This is recommended for now as other third party plugins will have not been tested on the latest beta versions.

To download AngularJS go to AngularJS.org and click on the blue "Download" button. Select the 'legacy' branch, which is the latest stable build, and click "Download".

Angular comes with something called 'jQLite' built in. It's a jQuery-like micro-library that Angular packages internally. jQLite is very light (as the name implies) and doesn't have many of the great jQuery methods that you might need. It's also good to consider that many plugins you might need will likely depend on the full jQuery library.

Good to know: Angular uses the full jQuery library if it's loaded - so I've loaded it before Angular so it can detect it and use it instead of jQLite.

When learning a new framework it helps to have something working as soon as possible. This enables you to play around and dig into what does what. But, before we can get there, we need to talk about Angular scopes and our first two directives: ng-app and ng-controller.

One of the most fundamental parts of Angular is scopes. Scopes hold your Models (that's your data), they cooperate with your Controllers, and they give the Views everything they need (that's what the user sees and interacts with). Angular scopes operate in a very similar way to the common JavaScript concept of scope.

The first scope we'll need is the application scope, this is exactly what you'd expect it to be: that's the scope your Angular application can operate in. We set this up in our HTML using the ng-app attribute.

<html ng-app="myApp">
<head></head>
<body></body>
</html>

Notice how we gave our app a name of 'myApp'. This will be usable in our whole html file.

Note: We can use ng-app without the "myApp" to declare a default app. In other words, just <html ng-app>.

The second scope is ng-controller; this will determine where our controller can operate. We can have multiple controllers within our application. Each controller will have its own scope. For example, we may have an inbox.html file, containing the below code. It will give responsibility to a controller named 'InboxCtrl' (in our JavaScript) for this scope.

This can be confusing! It often helps to see the code in action. View the result by downloading the Code check and opening the index.html file in your browser. Be sure to change the $scope.title's value as well as play around with the input.

The ng-view attribute here will tell Angular where we wish to inject HTML based on the URL a user visits.

In this sample project, we'll want to have an inbox view. When a user visits the /inbox URL our (yet to be created) inbox.html file would be injected inside the ng-view. The inbox.html file would also have it's corresponding controller (InboxCtrl).

Angular encourages the "single page application" methodology, which means we never get a full page refresh, all "pages" are injected content via XHR (Ajax). Of course these aren't "pages" as such, they're "views" - which are loaded depending on the URLs a user visits or the application state.

Looking at angular.module()

Every app needs a module, and Angular provides us with a namespacing capability for this using angular.module(). The method both sets and gets depending how you use it. To create (set) a new module we do this:

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

Notice the empty array, this is where we could put any other named modules as dependencies. Here we tell angular we're creating the module named 'myApp' with no dependencies.

To get a reference to a module, for registering controllers, factories, filters, etc… we drop the array and just call the module by name:

angular.module('myApp');

Note: When we specified the ng-app="myApp", the "myApp" part in the module should be the same. Another way to put it, the name of the app has to carry over.

The angular.module() method also returns a reference to the module which can make accessing it a little less verbose, however this pattern is discouraged due to potential problems with global variables:

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

Routing

The next logical step is to configure our routing, which controls which views are injected into the app based on which URL we're hitting. For example when we're at /inbox, we'll want to inject the inbox.html view and assign a Controller. We can use Angular's $routeProvider for this.

This is where the real fun begins!

RouteProvider

Since Angular 1.2.0, the $routeProvider hasn't been included in the main Angular build, so we'll need to include it as a separate module.

To download the $routeProvider (which lives inside angular-route) go to AngularJS.org and click on the blue "Download" button. Click on "Browse additional modules", select angular-route.js and save that file.

This file will give us access to an additional module named ngRoute, which we need to include (set as a dependency) in our own module:

var app = angular.module('app', [
'ngRoute'
]);

Config Stage

We saw before how to bind a Controller to the DOM (or to a specific view, to put it another way), which is just one way of doing it. Angular allows you to dynamically assign a Controller through the $routeProvider service, which is much more flexible. From now on let's use this instead of using ng-controller="" to declare Controllers.

Angular modules each have a .config() function, we give this a callback that is run before most other function callbacks in Angular. This is where we must configure our routes (the different URLs visitors will be able to access).

app.config(function () {/*...*/});

Dependency Injection

We'll need to use the $routeProvider to setup our routes inside the config callback; this is made possible via some magic inside the Angular framework (using function definitions and regex). We can simply accept $routeProvider as an argument to the config function and Angular will understand that we've asked for it.

app.config(function ($routeProvider) {
/* Now we can use the routeProvider! :D */
});

Now we can setup our routes using the $routeProvider in the .config() callback, see how we accept it as an argument and Angular will give us what we need:

The $routeProvider is really declarative and easy to use, we just declare what view template to use when the URL is pointing to a particular path. Working hand in hand with the ng-view attribute we previously set in our index.html, these template files will now be injected for the described routes.

Our app will have an inbox view, and a single view for injecting the clicked on Email into.

The first view will be injected at /inbox, and the second will be inbox/email/:id. You'll notice the second route has :id at the end - this is a dynamic view. It means that an object with an id as a property (with a value) will be used in the URL, which makes all views dynamic. We'll then use this to make a server call to get the email that corresponds with the id.

If you look closely, you'll notice each view has a particular Controller. Later versions of Angular (we're using one of the latest) ship with a new Controller syntax, the "Controller as" syntax, which instantiates the Controller like an Object and binds it to the current scope under a namespace. The namespace we've chosen for InboxCtrl is inbox.

Note: You can also declare "Controller as" in-line. It'd look like this: ng-controller="InboxCtrl as inbox".

Connecting the model and the view

Controllers are the middleman between the Model and the View, they drive the Model and View changes. Imagine that the controller is given some html from the route and a javascript object from the dependency injection; with these two things, the controller will tell the view (the html) what it can do by giving it scope variables and maybe a few functions.

Let's take a peek at what a Controller looks like.

A good Controller will have as little logic in it as possible, and should only be used for two things: Binding the Model to the View (initializing the View) and adding helper functions to the View.

If you go through the Angular documentation examples (available at AngularJS.org) you'll notice Model data being declared in the Controller. While this is okay for examples, the Controller easily becomes the Model as well - which is very bad for many reasons:

All the pieces start to get more coupled together

More difficult to share business logic

Makes things difficult to test

Remember: A good Controller will have as little logic in it as possible.

Each controller has access to a $scope and some html. $scope is the most documented way of adding properties and methods to our view. Remember how we said each 'ng-controller' attribute specifies a scope of HTML to manage? Well, that scope has access to the same $scope as the Controller function.

Note: $scope isn't the only way to pass data to the front end. Many developers use a combination of the "Controller As" configuration options along with the this keyword. For the purpose of this tutorial, we will stick with $scope as it's been around for much longer than 'Controller As'.

app.controller('InboxCtrl', function ($scope) {
// initialize the title property to an array for the view to use
$scope.title = "This is a title";
});

Note: Notice we're injecting $scope inside the function.

We can then use this like so:

<div ng-controller="InboxCtrl">
{{ title }}
</div>

Note: Here we're accessing the title directly, however it is encouraged to always have at least one dot (.) in our view expression properties. Using the "controller as" with this syntax would solve this giving us the . like so {{ inbox.title }}. More info here.

In order to keep our controllers more reusable, we would hook up data in our controller via a Factory or Service.

Make sure you've downloaded the code. Do this by going here and either cloning the reop or clicking "Download Zip".

In your terminal, navigate to the project folder (e.g. /Users/carl/Downloads/guide-intro-to-angular/app/03-application-controller)

Run a simple local server. On a Mac, you can do this by running python -m SimpleHTTPServer. If you're on windows, try doing this by installing Mongoose.

In your browser, go to http://localhost:8000/

What's a Factory?

Angular Factories can be used for many different things. Some of the most common use-cases are server-side communication via HTTP and abstracting Models to persist application state and changes across controllers. Angular Factories are a great way to create reusable features and code blocks throughout our application.

Key takeaway: If you want to communicate with a RESTful API, do it through a factory! If you want to store a 'CurrentUser' with authentication information, do it in a factory!

Note: You may have heard of factories as a design pattern in many programming languages, but Angular's factories are different to those in practice (maybe not in spirit :).

Notice how we're injecting a few different things here, such as: $rootScope, $http, $location. We'll cover these in a bit.

It's often good practice to create an exports Object inside your Factories and return it. This helps with explicit internal naming which helps you see which methods / variables are private or not (closuresftw).

In this app, we'll need to get our messages, so let's create a function to do that. Angular uses the $http service to communicate with the server, so we'll inject it:

This will use $http to make a GET request to our "json/emails.json" file; here we also set a default error handler for the http request by chaining a method onto the promise returned by $http.get(). Yes that's right, $http() returns a promise! So we can use all of the Angular promise API, the same as we would use a $q.defer().promise object, with a few extras: namely error(fn) and success(fn). success(fn) and error(fn) are two "sugar" methods that are very similar to then(fn) and catch(fn) but specific to $http. Don't worry if this goes a little over your head- we'll go into promises more in the next section!

Note: What are "sugar" methods? In simple terms, syntactic sugars are a feature in a programming language that lets you express an idea in a more convenient way.

Make sure you've downloaded the code. Do this by going here and either cloning the repo or clicking "Download Zip".

In your terminal, navigate to the project folder (e.g. /Users/carl/Downloads/guide-intro-to-angular/app/04-inbox-factory)

Run a simple local server. On a Mac, you can do this by running python -m SimpleHTTPServer. If you're on windows, try doing this by installing Mongoose.

In your browser, go to http://localhost:8000/

Connecting our Controller and Factory Together

Promises are very important inside Angular, they allow you to organize functions that take a long time to do things (e.g. HTTP requests). Promises in Angular are implemented with $q. The $q implementation was inspired by Kris Kowal's Q.

See how the InboxFactory factory is available as an injectable in our controller? That's dependency injection helping us out again!

We then call the getMessages method on the factory and using the $http()'s success method ($http() was returned from getMessages()), we can then add the list of emails / messages to our controller's $scope and use it in the view. i.e. The success(fn) is available from chaining when we do http() or http.get(), etc…

Rendering our Views

Let's talk a little more about the View files we've been using. You may have noticed that inside our template we were using the properties that we added to scope directly inside {{ }}. These are called expressions and we can put some basic JavaScript in there too, as well as a bunch of filters.

Angular will interpolate these expressions: above we have made use of 3 little examples of how powerful expressions are.

In the first one, we create an array and put two String $scope variables inside it, then we join the two together with a " " to display the name in a <h1>.

In the second, we multiply two Number $scope variables together and then apply a currency filter on them. You can read more about filters here in the Angular documentation.

In the third line of code we make use of a JavaScript ternary operator inside the expression to check whether the Number $scope property total is greater than the budget property and display the appropriate message in the div.

These templates are an essential aspect to Angular as we can not only make the mappings of data that you've seen already, but we can also introduce custom elements completely! In Angular these are called directives and come with their own templates (either in another html file or a string, the same as how controllers operate).

As you can see the name of the directive is camelCased (myCustomElement) whereas the html element is hyphen-separated (<my-custom-element></my-custom-element>). This is an angular convention for directive naming.

Next, we return a JavaScript Object with various properties on it to describe how the directive works. Here's a quick run through of what some of the Directive properties mean (feel free to skim through this):

restrict: allows you to restrict how the element is declared, E = Element, A = Attribute, there are other ways of declaring (such as a comment) but I wouldn't recommend them as they're not that friendly with older browsers.

replace: replaces the Directive's root element, in this case would be <inbox></inbox>.

scope: tells Angular to use an isolated or inherited scope, these concepts are quite tricky to grasp, but setting to true inherits the parent scope and keeps sibling directives more independent, which makes things easier to work with. There are cases where isolated scopes (scope: {}) are the better choice depending on what we're doing.

template: I've recently used an [].join('') style for templating, it's much cleaner to work with and we can start the first line of the template on a new line, rather than having a huge indent.

templateUrl: the same as template, but will point to a template file such as tmpl/inbox-directive.html instead of being a string.

controllerAs: creates a namespace for our Controller when instantiated

controller: inject dependencies and bind logic, you may also expose an API for other directives to interact with this one through the 'controllerAs' and this of the controller.

link: a place to write non-Angular logic, but tie it in with Angular. You'll have access to the current scope, the template element root (first element in template rather than Directive root) and the attributes on the element declared.

Now we can use this directive anywhere in our application's scope by creating an <inbox></inbox> element (using restrict: 'E' to specify an element directive).

When the application runs, Angular will replace the <inbox> element with the template at the templateUrl. We then make an alias for the controller under the name of inbox. This alias is then accessible inside the controller as this and inside the template as inbox. If you look inside the template you'll see expressions like inbox.messages and inbox.deleteMessage(id, $index). These are the same this.messages and this.deleteMessage we can see in the InboxFactory.

Finally we have a link function that will run straight after the controller runs. The link function will then receive the aliased controller as the fourth argument, here we named it ctrl. Yes that's right, the link function has fixed positions for it's arguments i.e. scope is always first.

Note: This is different behavior to the controller's arguments which are injected and therefore can take any order. For the link function we don't use the $ prefix for scope, element and attributes to make it clear that they aren't under the control of dependency injection.

Notice the use of built-in angular directives such as ng-hide, ng-show, ng-click, ng-repeat and ng-model. We won't go into much detail about these directives as each can be quite a big topic but you can read about them here.

View the result by downloading the Code check and opening the index.html file in your browser. Play around with the fruits values inside index.html and refresh your page to see how everything updates.

Note: Cloaking is a bit of an advanced trick but we thought you might enjoy it :) Feel free to skip over this section if you'd like.

Angular has a really neat built-in feature called cloaking, which you can declare on an Element to tell Angular it needs cloaking (hide it) whilst it's still rendering. Cloaking allows you to hide any handlebars you might see flicker before Angular has rendered and loaded your data. E.g. {{user.name}} before the user data has had time to load.

When lib/angular.js has loaded, AngularJS automatically appends an inline <style></style> element to your document with cloaking styles to hide elements during load. This can sometimes take a second to load as it's got a JavaScript dependency too, so I recommend setting up the <head></head> of your document manually like this:

This is 100% reliable and hide any cloaked elements immediately, even without Angular loaded. Applying cloaked styles is easy:

<div ng-cloak>
{{ someData }}
</div>

Debugging in Angular can be very difficult and frustrating. This section will give you the foundation you need to simplify the process.

Stack Trace Function Names

Angular uses a lot of anonymous functions in the call stack. When these throw an error (yes, you'll see a lot of errors during development), to make things easier to debug, I've named anonymous functions.

Here it is before:

app.factory('InboxFactory',
function ($q, $http) {}
):

...and now after:

app.factory('InboxFactory',
function InboxFactory ($q, $http) { }
):

This will then show errors at InboxFactory rather than at anonymous. A handy tip for developing Angular apps.

Routing Problems

Another debugging tip when working with routes is to listen for Routing Events to be triggered on the $rootScope. A suitable place for this is the run function, found here, which can be thought of as a 'controller for the module', but try to keep this section as small as possible!

We've made a bunch of changes to the project to give it a more complete feel, here's a list of what we did:

We added a new route for specific Email messages that accepts an :id parameter

We added some slick CSS styles :)

We changed our controllers to all make use of the 'Controller As' syntax

We added the ngSanitize library to use the ng-bind-html directive in the Email directive

We uncommented the goToMessage method in our Inbox Factory that will navigate to the new route

We simplified our controllers further so they now only use the title on 'this' (Controller As)

We added the Email Controller and view

We added the Email Factory which adds a bunch of factory and JavaScript alerts where server communication would be appropriate

We added the Email Directive and its template as well as using it in our Email View

We added new JSON files for each of the messages

We added the ng-cloak, however it isn't used in this application as ngView covers this for us :)

I would encourage you to have a read through the code and try to understand what's happening. You may of course find much more suitable ways to accomplish the same results to your own liking, this is just an example for learning purposes but we've been sure to include a number of good thinking points for you to work from.

You may be able to find some other little tricks we've included such as $timeout, ng-bind-html and last but certainly not least $watch.

Make sure you've downloaded the code. Do this by going here and either cloning the reop or clicking "Download Zip".

In your terminal, navigate to the project folder (e.g. /Users/carl/Downloads/guide-intro-to-angular/app/03-application-controller)

Run a simple local server. On a Mac, you can do this by running python -m SimpleHTTPServer. If you're on windows, try doing this by installing Mongoose.

In your browser, go to http://localhost:8000/

Congratulations! You just finished the Angular guide. Click here to share with the world :)

When moving from something like website development to Angular you can be tempted to use jQuery selectors (since you already know how to use jQuery). You need to avoid doing that. Angular takes care of the DOM. Do not modify it yourself, unless you really need to or are using a plugin. Anything you'll likely want to do, Angular can do.

With Angular, the ng-model will keep this updated for us, we just reference it:

<textarea ng-model="myModel"></textarea>
<script>
app.controller('SomeCtrl', function SomeCtrl($scope) {
// binds and keeps the value updated at all times
// no need to re-query the value at any time
// which means we can pass the value straight
// back to the server for example
$scope.myModel = '';
})
</script>