AngularJS is a client-side web application framework that reimagines HTML.

Let that sink in. If you are an experienced web developer, you have probably already compared Angular to familiar JavaScript frameworks and libraries, such as jQuery, Knockout, Backbone, Ember, and possibly even React. Similarly, if you know something about GUI programming, you may have tried to relate Angular to Model View Controller (MVC) or Model View ViewModel (MVVM). These impulses are natural, but they can cloud your understanding of Angular. For this chapter only, I would ask you to let go of thinking of Angular as a JavaScript framework. Hold off for a moment on trying to understand how it works under the hood. Take Angular at face value. Experience it just as a powerful set of extensions to HTML.

We'll start with three fundamental Angular constructs: expressions, directives, and scopes. However, before we get into the examples, let's quickly review how to get Angular working in a web page. (Or, skip ahead to start the section on expressions.)

Set up

Where do you get Angular? While you can download it from the official site, loading Angular into your page from Google Hosted Libraries (a CDN) is both convenient and likely to perform well. The live examples in this page do so by including the script tag shown below within the head element.

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.js"></script>

After including the Angular library file, you need to let Angular know which part of the HTML document it should manage. Remember that Angular is HTML-oriented rather than JavaScript-oriented. Rather than writing some JavaScript to load it, we instead add some non-standard HTML that Angular will recognize. This is a special ng-app attribute that we can add to any element in the DOM. For the examples in this chapter, we will place it on the body element, as shown below. By choosing to put it on the body or html element, we give our Angular application control over our entire page. You can pick a narrower scope if you like, which allows you to use another framework alongside Angular, or even load additional Angular applications. This makes sense for a more traditional, document-oriented web site in which client-side code is contained within isolated widgets, rather than a single-page application (SPA).

<body ng-app>
  <!-- Other examples in this chapter will be inserted here. -->
</body>

With this magic attribute, we now have Angular working in our page. Now then, what can we do with it?

Expressions

Be warned: If you have been trained in the doctrine of unobtrusive JavaScript, the following examples may set off alarm bells, as Angular's first order of business is to allow you to mix JavaScript-like expressions into your HTML. Angular expressions can be almost any simple, valid JavaScript, although flow control structures like loops and some other things are not allowed. Please suspend judgement as we explore the boundaries of what is permitted (but not necessarily in good taste) through some old-fashioned experimentation.

Let's start by adding two numbers. Like all of the code in this book, the listing below is a live editor that lets you modify the example. You may change any part of it. The output is rendered within an iframe sandbox and will be instantly updated.

<p>The number {{3 + 4}}.</p>

Go ahead, replace 3 + 4 in the live example above with a different math expression. See if you can find something that Angular won't or can't handle. (When Angular fails to process an expression, it either outputs the original string, or in the case of some errors, nothing at all.)

The double curly brackets are template delimiters. If you are familiar with Mustache or perhaps Handlebars, then you have seen double curly brackets used this way before. One way to think of Angular is just as a really sophisticated templating library. It treats everything within the element you marked with ng-app as a template that is compiled when your page loads, and re-rendered whenever there are changes to data. (Don't worry if you are unfamiliar with templating; we'll cover the basics of it later.)

How about testing the equality of two values? Sure, we can do that too.

<p>Are strings and numbers equal? {{'2' == 2}}</p>

The result is correct for JavaScript. If you're surprised by it, quickly review JavaScript comparison operators, then change == to === in the example above. (Strict comparisons are better, right?)

Here is an example that concatenates strings and also demonstrates that we have access to standard library functions such as String's toUpperCase instance method.

<p>{{"Angular" + "js".toUpperCase()}}</p>

Are you getting the feeling that you can do whatever you want inside expressions? Not so fast, partner.

<!-- Invalid code! This function call is not permitted in an expression. --> <p>{{alert("Hello world")}}</p>

You definitely can't use alert. Nor can you access most of JavaScript's global objects, such Math, Number, Date, and so on.

Try replacing alert("Hello world") in the example above with parseInt("1"), Date.now(), Number.NaN, and Math.random(). If no output is shown, Angular has refused to parse the expression.

Although Angular limits what you can do in expressions, I suspect you will exhaust your tolerance for mixing code and markup before you feel constrained by the framework. Let's probe the limits in any case. Do you think we can assign variables?

<p>{{a = 1; a + a}}</p>

It works. But try adding the var keyword before the variable name. Do you get an error? If you see the raw expression including the delimiters in the output, you have caused an error. Do not feel bad. Breaking things is a great way to learn.

So is experimentation. I do not know if a variable assigned inside one set of delimiters can be used within another. Why not try?

<p>{{a = 1}} remains {{a}}</p>

Yes, it works. What if you move the initialization of the variable to the second expression? Go ahead, try it. Does it work? Can you guess a possible reason why?

Ok, expressions support assignment. What about the ternary operator?

<p>There {{count = 1; (count == 1 ? "is " : "are ") + count}} of them.</p>

Fortunately that works as well, since the ternary operator offers a concise syntax that can be really useful in templates.

Now, what about the increment operator (++)? Can we use that?

<p>{{a = 1; ++a}}</p>

Apparently not. Still, what about a for loop? We'll avoid idiomatic use of var and the increment operator, since we've already disqualified those.

<p>{{for (i = 0; i < 10; i = i + 1) {i}}}</p>

The for loop is not executed. It produces a syntax error that you should be able to see in your browser's console. But there is nothing invalid in the JavaScript in this statement. In the browser's console, paste the statement for (i = 0; i < 10; i = i + 1) {i};. It should evaluate to 9. Go ahead, try it. So, we have hit a few boundaries: Angular expressions are not JavaScript. The expression language does not support conditionals, loops, or throwing errors.

We have likely pushed things far enough with expressions. Personally, I am ok with some JavaScript in my markup when it is concise and view related, so I appreciate the relatively permissive nature of Angular expressions. However, any more than just a little JavaScript within a template rapidly becomes unsightly and confusing. Fortunately, expressions merely play a supporting role in Angular. We should never feel the need to place too much code within them.

The real key to Angular's mind-blowing productivity is the directive.

Directives

Directives are the heart and soul of Angular. I recommend that you start out by thinking of them simply as custom HTML. Most of the time, directives appear in the form of attributes that can be used on normal, familiar elements. The built-in directives that come pre-packaged with Angular generally start with an ng- prefix, which is a reference to the “ng” in Angular. There are also countless third-party directives now available. “There must be a directive for that” should be your standard reaction when you see verbose JavaScript within an Angular expression.

We have already used a directive. Do you remember it? To get Angular working in the live examples in this chapter, we added ng-app to the page's body element. (Go back for a look.) In this case, we used the directive without passing any arguments to it. When you pass arguments to a directive, you simply use ="", just as you would with a normal HTML attribute. For example, we could pass in the name of application with ng-app="myApp". (The application name is actually the name of a module, an important part of Angular's architecture that is covered in the Modules chapter.)

ng-bind

Some directives accept and parse string expressions. (You can verify the parameters for a built-in directive by visiting its API documentation.) For example, the ng-bind directive simply renders expressions, just like the double curly brackets that we used in the previous section. This is what it looks like.

<p>The number <span ng-bind="3 + 4"></span>.</p>

While this simple usage results in exactly the same output as the first example above, there is an important difference in the behavior of ng-bind: The content of the element to which you apply ng-bind is replaced when the template is rendered. Therefore, the preferred technique is to use ng-bind but to not put anything inside the element, with the result that during the brief moment before Angular replaces your raw template, nothing is shown. This can be advantageous. Depending on the user's environment and the size and behavior of your Angular application, there can be actually be a delay that allows users to see the double curly bracket delimiters and expressions in your uncompiled page content. Using ng-bind on empty elements avoids this.

At some point as your Angular application grows in size, you may want to address these flicker issues at a higher level by hiding most or all of your content until Angular has loaded. This is easy to do with the ng-cloak directive. See why “there must be a directive for that” is the right mindset?

ng-init

Remember how we initialized a variable in an expression, just to see if it would work? Well, you guessed it: There is also a directive for that. With ng-init, you can initialize variables for use anywhere within the element to which it is applied.

<div ng-init="sum = 3 + 2"> <p> {{sum + 1}} is more than <span ng-bind='sum - 1'></span> </p> </div>

Using semicolons to delimit statements, you can initialize as many variables as you like.

<div ng-init="count = 7; units = 'days'; collection = 'week'"> <p> There are {{count}} {{units}} in a {{collection}}. </p> </div>

At some point, you may find it better to organize your variables as the properties of an object.

<div ng-init="time = {count: 12, units: 'months', collection: 'year'}"> <p> There are {{time.count}} {{time.units}} in a {{time.collection}}. </p> </div>

Arrays are also useful.

<div ng-init="months = ['January','February','March','April']"> <p> {{months[3]}} follows {{months[2]}} in {{months}}. </p> </div>

It is important to be careful about property names when coding Angular templates. You can probably spot the errors in the template below by looking, but don't expect any help from Angular. It quietly tolerates all property access errors, including nested properties on nonexistent parents and out-of-bounds array access.

<div ng-init="paragraph = {sentence: {words: ['first','second','third']}}"> <p> "{{typo.sentence.words[0]}}", "{{paragraph.typo.words[1]}}", "{{paragraph.sentence.typo[2]}}", "{{paragraph.sentence.words[3]}}". </p> </div>

My personal wish is that instead of being so tolerant, Angular had employed something like CoffeeScript's wonderfully concise existential operator (?) to make these silent access failures an option rather than the rule.

Given Angular's permissiveness so far, do you think we are permitted to declare functions within ng-init? What would you guess?

<div ng-init="count = function() { return 12; }"> <p> There are {{count()}} months in a year. </p> </div>

No, the function expression above is not allowed. While trying to process the argument to ng-init, Angular throws a $parse:syntax error that you can see in the JavaScript console of your browser. The correct place to declare functions for use in Angular expressions is within a controller, as we will learn in the upcoming Controllers chapter. In fact, controllers are the proper place to prepare application data for the view. The ng-init directive, while fun to play with in this chapter, is actually intended for aliasing variables as a way to cope with variable shadowing, as we shall see in the Collections chapter.

ng-non-bindable

By the way, if you need to shield some part of your document from Angular's processing, adding ng-non-bindable to an element will exclude its contents from compilation.

<p ng-non-bindable> {{2 * 2}} is the same as <span ng-bind='2 + 2'>?</span> </p>

Remove the ng-non-bindable directive from the example above to see what happens.

ng-show

It is time to explore something more than simply rendering expressions. For starters, how can we conditionally display or hide an HTML element?

I can offer some advice from my own experience of how not to do this with Angular. The very first time I used Angular, I needed to hide a form after the user successfully submitted it. Inside a controller that I had created to handle the user action, I added a call to jQuery.hide(). It worked, of course, and if you are learning Angular within the context of a fast-paced project, sometimes you need to be pragmatic. However, “there must be a directive for that” would have served me well. Indeed there is. Two directives, in fact: ng-hide and ng-show.

We can demonstrate the use of both at the same time.

<p ng-init="authorized = true">
  The secret code is
  <span ng-show="authorized">0123</span>
  <span ng-hide="authorized">not for you to see</span>
</p>

Change true to false in the example to see what happens. Since Angular is always watching for changes, you can toggle the value of a variable like authorized anywhere you have access to it, and the view will be updated for the user.

At this point, it is probably time to go a bit more in depth about variables like authorized and understand what they actually are.

Scopes

Scopes provide a single source of truth within your application. The idea is that no matter in how many places you display some data in your view layer, you should only have to change it in one place (a scope property), and the change should automatically propagate throughout the view.

Since this automatic rendering and re-rendering requires infrastructure, the most notable thing about the JavaScript objects that you set on Angular scopes is how ordinary they appear. You may be familiar with the concept of plain old domain model objects. The original is the Plain Old Java Object, or POJO. When the POJO idea was first explained by Martin Fowler, he meant the basic, ordinary objects directly provided by the core language runtime, as opposed to unwieldy domain model objects that inherit special capabilities from a framework superclass. However, the term was extended to mean objects that appear plain but which are transparently enhanced by a framework with special runtime capabilities, typically persistence.

The objects attached to Angular scopes are JavaScript POJOs, since Angular applies sophisticated change detection at runtime in order to propagate changes. When the Object.observe language feature makes it into mainstream JavaScript, Angular may truly become a plain old JavaScript framework.

We have already seen scope properties in this chapter. Remember the variables that we initialized inside expressions and using ng-init in the examples above? These are all scope properties. Remember when I asked you to add the var keyword to an expression? Using var is prohibited because what I previously called variables (my apologies for the deception) are in fact properties on a scope object that is automatically created for us behind the scenes. The next chapter will cover scopes in greater depth. Right now let's get into some hands-on examples that demonstrate how we use scope properties.

Two-way binding

So far, we have seen examples of one-way binding, in which scope data is dynamically updated in the view. Things really get exciting when you use HTML controls to modify this data. Together with the view updates, this is referred to as two-way binding.

For a primitive first example, we can use the ng-click directive to modify a boolean property.

<p ng-init="authorized = true">
  The secret code is
  <span ng-show="authorized">0123</span>
  <span ng-hide="authorized">not for you to see</span>
  <br>
  <input type="button" value="toggle" ng-click="authorized = !authorized">
</p>

The argument to ng-click can be any expression. Although it is a versatile directive that is not limited to acting upon scope properties, the inline code for flipping a boolean works well since it is so simple. But how do you bind more sophisticated inputs and data types?

ng-model

It seems like every introduction to Angular demonstrates data binding with a text input and a string property. Finally, it's our turn.

<input type="text" ng-model="title">
is bound to
"<strong ng-bind="title"></strong>".
Type something in the box!

This example is the poster child for two-way binding. When we add the ng-model directive to the HTML input element, Angular wraps the default HTML control in its own input directive.

What more can we do? Well, we can always use ng-init to provide an initial property value.

<input type="text" ng-init="title = 'Angular'" ng-model="title">
is bound to
"<strong ng-bind="title"></strong>".
Change it!

Let's try some other input types. Here is a checkbox.

<input type='checkbox' ng-init='optIn = true' ng-model='optIn'>
is bound to
<strong ng-bind="optIn"></strong>.
Change it!

The value bound to a checkbox can be a string rather than a boolean if you set the ng-true-value and ng-false-value parameters.

<input type='checkbox' ng-init='feeling = "love it"' ng-model='feeling'
    ng-true-value='"love it"' ng-false-value='"hate it"'>
is bound to
"<strong ng-bind="feeling"></strong>".
Change it!

Angular's select directive works as you might expect. Notice that it ignores the selected attribute on the first option. Remove the ng-init directive and you will see that selected still has no effect.

<select ng-init='answer = "maybe"' ng-model='answer'>
  <option value='yes' selected>Yes</option>
  <option value='no'>No</option>
  <option value='maybe'>Maybe</option>
</select>
is bound to
"<strong ng-bind="answer"></strong>".
Change it!

With just three options, the last example might work better as a group of radio buttons. No problem, let's change it.

<div ng-init='answer = "maybe"'>
  <input type='radio' ng-model='answer' value='yes'> Yes
  <input type='radio' ng-model='answer' value='no'> No
  <input type='radio' ng-model='answer' value='maybe'> Maybe
  is bound to
  "<strong ng-bind="answer"></strong>".
  Change it!
</div>

You now have some real-world experience manipulating scope data using Angular directives. There are many more built-in directives, and we will explore a number of them in the upcoming chapters.

Conclusion

At the beginning of this chapter, I asked you not to think of Angular as a JavaScript framework, but rather as a set of extensions to HTML. As Angular creator Miško Hevery recounts in this fascinating interview, Angular was originally conceived as a radically more productive way for front-end developers to enhance web pages. The JavaScript framework came later.

Central to Angular's original strategy is the premise that a declarative programming style is the best fit for rapid GUI development. However, rather than asking developers to invest in a new domain-specific language (DSL) for web development, as was attempted with MXML and XUL, Angular builds upon the widespread familiarity of HTML.

So much for the vision. For the moment at least, Angular is virtually never used without custom JavaScript. Real-world Angular applications almost always make use of controllers, services, and routers, as well as supporting modules, dependency injection, and Ajax infrastructure, all of which is covered in this book. However, the productivity promise of Angular is still best realized when a web developer is able to work mainly in the declarative space, with a degree of confidence that “there must be a directive for that.” Writing custom directives to fill the gaps is one of the more challenging areas of Angular, which is why this chapter tries to start your Angular journey with the end in mind. Now that you understand that the ultimate goal is productivity-boosting extensions to HTML, rather than just writing JavaScript code within a framework, you are better prepared to dive into the details.

I hope you have been enjoying Angular Basics.
You can join the mailing list to hear about updates to the book.
Please also let me know what you liked and what I can improve.
And please share the word using the social buttons below!