What In The World Is AngularJS?
- Option B You be a good developer, who cares about separation of concerns, and split all those tasks in several components where each is in charge of a single thing; those written in separate files for your code maintainability’s sake, while making a lot of friends in the process.
Of course, option B is the way to go. Since there is a ton of things going on in the browser, we need a way to create components that handle each task separately. This is known as the Separation of Concerns principle, or SOC; which states that your code has to be split in several parts, handling a single task each, orchestrated in order to achieve a common good. And this is where AngularJS shines. It allows you to:
- Organize your client-side code in a Model-view-controller fashion, so you have separate components where each handles a different task in the logic stack: from user input to server data posting (Don’t worry, we’ll get on this later on.)
- Live template processing and data-binding; more specifically: munch a template, bind it to specific data coming from the server or anywhere else and then produce a valid HTML piece that can be displayed in the browser.
- Creation of re-usable user interface components.
- Implementation of advanced patterns, like dependency injection; which is tied to…
We all know Model-View-Controller (MVC from now on) was conceived for a good reason: Roles and responsibilities matters. It was designed as a practical way to separate all of the front-end logic into three interconnected parts, so code having to do with how data is displayed is clearly separated from the code that validates, stores and retrieves that data. Also, it was thought with unit testing in mind.
MVC Flow Now, MVC is commonly used server-side; think of ASP.NET MVC or Spring MVC, where you have a class representing the “controller”, which fetches data into “models” and then binds them to a template producing a “view” in the form of an HTML document, which is returned to the browser for display on the user screen. Remember, each time we talk about MVC, we are generally referring to the Presentation Layer of an application.
OK, enough talk already. Let’s dive into how to implement a simple application using AngularJS.
Consider the classic “To-do List” example. We want a screen that displays a list of items to be completed; also we need to show a mini-form that allows us to enter and add new items to the list. Here is how it should look:
So, in order to get this done, we need to complete some steps:
- Create the HTML document which will be representing our view.
- Include the AngularJS library in the HTML document so we can start creating controllers that will handle behavior of the user interface.
- Add scope (almost there…) variables and functions that will be bound to the view through special AngularJS HTML attributes.
Basic View Markup
Let’s start this in a natural way: let’s create the user interface first. We will create a file called todolist.html and we will add the following HTML to it:
Now, nothing fancy right there; we just included the AngularJS library at line 8 and another file at line 9, which we will create in a moment. However, just notice the structure of the document: We have an UL element which will represent our list of to-do items and then a couple input controls so we can add new items to the list. It does not have any information on it for now, but eventually it will… And it will be awesome.
Let’s leave this code as it is for now, let’s move to the app.js file which has all the fun going on.
Adding Logic: The Controller
Just by looking at the previous HTML document, you will realize that there are two things we need regarding to view state data:
- An array to store the to-do items to be displayed in the UL element at line 13.
- A function to add new items when I click the Add button at line 15.
Simple, right? Well, let’s create a new file called app.js and add the following code; I’ll explain it later:
First things first: let’s take a look at line 1. Before we start building controllers that handle UI logic, we need to create what is known as an AngularJS application module; this is done by calling the angular.module() function and passing it the module name, which returns the created module. This object will later be used as a container where you will store all of the controllers belonging to this particular JS App.
The variable angular is available after we included the AngularJS library in our HTML document at line 8.
After we create the application object, we can start creating controllers; being done in line 3 through the controller() function, which is now callable from the application module we created in line 1. This function takes two arguments: the name of the controller and a callback function that will be responsible of initializing the controller and which will be called each time a controller is instantiated by AngularJS. AngularJS also passes a special variable to that function called $scope; everything that is added to the $scope variable during controller initialization, will be accessible to the view for data binding; better said: it represents what the view can see.
The rest of the lines are quite self-explanatory:
- Lines 7 to 11 adds a pre-initialized array of to-do items to the scope, that will be used as storage for new items. It represents the items that will be displayed in the empty UL element we have right now.
- Line 13 declares a variable that will hold the description of new items to be added after the Add button is clicked.
- Lines 17 to 21 define a function that will add new items to the to-do items array; this should be called each time the Add button is clicked.
Binding The View
Now that we have AngularJS, the application module and the to-do list controller, we are ready to start binding HTML elements in the view to the scope. But before that, we need to change our tag a little and add some special AngularJS attributes:
Notice the ng-app attribute we added to the tag; this is your first contact with one of the several directives that are part of the AngularJS data binding framework.
Directives are simply HTML element markers that are to be processed by the data binding engine. What does ng-app do? Well, it tells AngularJS which application module it should use for this HTML document; you might notice we specified ToDoListApp, which is the one we created in out app.js file at line 1.
After we associate our HTML document with the ToDoListApp, second step is to specify a controller for our view; this is done through the ng-controller directive. The ng-controller directive assigns a controller to a section of the HTML document; in other words, this is how we tell Angular where a view starts and when it ends.
Anyways, modify thetag so it looks like this:
Same with the ng-app directive, the previous code tells AngularJS that everything inside thetag will be governed by the ToDoListController, which we created in our app.js file at line 3.
Now we are ready to start binding elements to members added to the $scope variable during the ToDoListController controller initialization.
The ng-repeat Directive
Let’s start with the empty UL list element. In this case we want to create a new child LI element per item that is contained in the to-do items array. Let’s use the ng-repeat directive for this matter; add the following code inside the UL tags:
OK, hold on tight. The ng-repeat directive will repeat an element per item in an array used as data source; the quoted value represents the iterator expression, which defines the array to be iterated and an alias used to refer the current item being iterated.
In this case, we specified that it should repeat the LI element for all of the items in the items array defined in the $scope variable from line 7 through 11 in the app.js file.
Lastly, inside the LI tags we define an Angular template, which is an expression enclosed in double curly braces that will be compiled dynamically during run-time. In this case, the template is extracting a member named desc from each item and is going to display its value inside the LI tags being repeated.
Go ahead, save your files and open todolist.html in your preferred browser; you will see how the list gets filled. Awesome stuff, huh?
The ng-model Directive
Next in our list is the ng-model directive, which is used to bind the value of an input element, a text box, text area, option list, etc.; to a variable of the $scope. But before I give you more talk, change the input element at line 15:
Binding the value of an element means that each time the value of the input element changes, the variable specified in the ng-model directive will change with that value.
In this case, the input element has been bound to the newItemDescription variable of the $scope, defined at line 13 of the app.js file. Each time the value of the input element changes, the variable at the scope will be updated and viceversa.
The ng-click Directive
What if I want to do something when I click that? For that, AngularJS provides a bunch of event handler directives. These directives can be used to invoke functions defined on the $scope each time the user performs an action over an element.
The only one we are going to use for this example is the ng-click, which handles the user click on a button or input element; the expression it takes is basically the code to be executed on each click. In our case, we will modify the button element at line 15 and add the following directive:
If you look closely, we are telling AngularJS to call the addItem function defined in the $scope. If you see the code of that function from line 17 to 21, you will see that it adds a new item to the to-do list array, based on the value of the newItemDescription variable.
If you save your files and open todolist.html, you will see how the list is automatically updated each time you enter a new description in the text box and click on Add.
Your HTML document is dynamic and alive. How cool is that?
What Kind Of Sorcery Is This!?
OK, I must tell you that all of this does not happen through magic. AngularJS is what’s called an unobtrusive library; which means that everything happens automatically as soon as the library finishes loading.
At the very beginning, when the HTML document finished loading, AngularJS crawls through HTML document structure looking for ng-app directives which tells it that something has to be done there. After all of the directives have been found, the marked elements are processed separately: elements are bound to controllers and templates are compiled.
The $scope variable lifetime is automatically handled by AngularJS, each time something happens on-screen, it is notified and performs anything that has to be done to ensure the controller and view are synced; from updating values in the $scope bound to a particular element to refreshing an element or template. This is done through the implementation of some sort of the observable pattern that allows AngularJS to react to changes on elements and the $scope itself.
Woah! That was a bunch of stuff to digest. Hopefully, you will make sense out of it with some practice. Of course those three directives are not everything that there is on AngularJS; for a complete list on all of the possible directives you can use out-of-the-box, take a look here.
Have in mind that you can also extend the library with custom directives, but that is an advanced topic we might cover in a future article.
AngularJS is not everything there is about JS Apps, this was a very basic introduction and I want you to have knowledge you can use in real life, so we will be learning how to build more complex JS Apps in my next article. Topics to be covered will be:
- Creating custom Angular directives.
- Complex user interfaces (windows, redirection and data validation.)
Hope that sounds exciting enough for you. Stay tuned! :D