Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Angular: The DOM API You Have Been Waiting For

4.00/5 (3 votes)
19 Nov 2013CPOL4 min read 12.9K  
Angular: The DOM API You Have Been Waiting For

Introduction

Angular.js, a JavaScript library and framework created in Google, is a fresh view into building great web applications. You can read a lot of articles on how it separates the concerns of the application, improves testability, and keeps to web app best practices, but I want to highlight a feature that is not shown off as regularly, extending the document object model API.

What you will learn

  • Angular template basics
  • Template secret sauce
  • Domain specific syntaxs

What you should know

  • Basics of HTML
  • JavaScript basics

Let's jump right into it and build a twitter timeline user interface. I would like to show my recent tweets and allow the user to click on any tweet and highlight it.

Template 1. Angular Template

<ul>
  <li ng-repeat="tweet in tweets" class="tweet {{tweet.highlight}}" ng-click="selectTweet(tweet)">
    <h4>{{tweet.text}}</h4>
    <ul ng-show="tweet.entities.hashtag.length == 0">
      <li ng-repeat="hashtag in tweet.entities.hashtag">{{hashtag.text}}</li>
    </ul>
    <span ng-repeat="user in tweet.contributors">
      <span>@{{user.screen_name}}</span>
    </span>
  </li>
</ul>

Here we have an example angular template, to show how flexible your template can be. There are a couple things going on here so I will break it down.

<li ng-repeat="hashtag in tweet.entities.hashtag">{{hashtag.text}}</li>

The directive 'ng-repeat' is used a couple places in this example because it is very powerful. It both repeats the element for each in an array and adds that object to the scope of the element. It does not change the scope, which is an important distinction from other template engines like handlebars.js where '../' is needed to access values outside of the object scope. Angular does use the mustache syntax of {{}} to insert values.

<ul ng-show="tweet.entities.hashtag.length == 0">

The directive 'ng-show' tells angular to show or hide depending on the statement you pass in. There are a variety of statements you can use here, so it adds a good amount of flexibility. Its important to note here, we are not giving this directive JavaScript, but a string that is parsed by angular. '==' is not the same as '==' in JavaScript and acts more like '==='.

<li ng-repeat="tweet in tweets" class="tweet {{tweet.highlight}}" ng-click="selectTweet(tweet)">

'ng-click' shows off something else that is different about angular, there is direct binding to the controller scope. Let me show off what the controller looks like.

Controller 1. Angular Controller

function($scope) {
  $scope.tweets = Twitter.getTimeline('1950787875');
  $scope.selectTweet = function(tweet) {
    if(tweet.highlight === 'highlight') {
      tweet.highlight = '';
    } else {
      tweet.highlight = 'highlight';
    }
  };
};

As you can see, when angular calls the controller function it is going to pass the scope into the controller function. Scope is the object that connects the view and the controller. Let's pretend in this example that we have a global object Twitter that has a method getTimeline that returns an array of tweets when called with a user id. When we set 'tweets', angular will use that to render the template into the DOM. 'ng-click' will link the click event on that element to the function selecTweet in the scope, allowing you to also pass arguments. It's important to note here also, what you pass to 'ng-click' is not run directly in JavaScript, but parsed by angular. Don't let that trip you up.

This shows off the basics but we haven't gotten into the power of angular templates. Angular is designed to build a domain specific language. This allows you to effectively extend the DOM just for your app. Let me show you what that template will look like.

Template 2. Angular Template with Custom Directives

<ul>
  <li ng-repeat="tweet in tweets" class="tweet {{tweet.highlight}}" ng-click="selectTweet(tweet)">
    <h4>{{tweet.text}}</h4>
    <entities ng-model="tweet.entities"></entities>
    <div ng-repeat="user in tweet.contributors">
      <user ng-model="user"></user>
    </div>
  </li>
</ul>

If you know your html you will notice quickly that <entities> and <user> are not HTML elements. These are angular elements that are created for this application. <entities> takes a list of entities passed in by 'ng-model', and renders them. <user> does a similar thing with a user object. This cleans up our main template here, and makes the template extendable and reusable. Both entities and user now have their own templates.

<ul ng-show="hashtags.length == 0">
    <li ng-repeat="tag in hashtags">{{tag.text}}</li>
</ul>

Here is the entities template. As you can see, the template is cleaner here, but also we can now user entities in other locations in our angular app. Once we put the <entities> tag all over our app making changes is simple. The secret sauce of angular I am showing off here is directives. Directives are a collection of functionality that can be added to any element in the DOM and show up in a couple different ways. I just showed you 'ng-*' and '<*></*>'. These two act differently, one adding on functionality to an element and another creating a new element, but they are based around the same idea.

Right out of the box we get a quick list of tweets presented in a way we are used to, <li> elements. If we need more power, we can build our own elements through domain specific directives. We have the ability to quickly add event listeners on these elements, and bind model values to element text.

I'm not arguing that you cannot do this with other frameworks but with angular.js you have a set of tools that take the DOM and extends it to make dynamic applications simple to write and understand. Add in support from Google and a growing, smart community of developers and you have a great framework that every JavaScript developer needs to try.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)