Developer Guide: Compiler

Work in Progress This page is currently being revised. It might be incomplete or contain inaccuracies.

Compiler

While angular might look like just a cool way to build web applications, the core of angular is actually an HTML compiler. The default HTML transformations that this compiler provides are useful for building generic apps, but you can also use them to create a domain-specific language for building specific types of web applications.

The compiler allows you to add behavior to existing HTML through widgets, directives, and text markup.

All of this compilation happens in the web browser, meaning no server is involved.

The compilation process

This section describes the steps that angular's HTML compiler goes through. If you use ng:autobind in your application, this compilation process happens automatically when the application is initialized (e.g. when the user loads the app in a browser). If you're an advanced user using manual bind mode, you can decide when and how often the compilation happens.

First, a bit of background of what the compilation step is for. Every type of widget, markup, and directive in angular is defined with a compile function, and that compile function returns an optional link function. Here is the relationship between the two:

Note that angular's built-in widgets, markup, and directives have predefined compile and link functions that you don't need to modify. However, if you're writing your own widgets, markup, or directives, you write compile and link functions. Refer to the Compiler API for more information.

When the HTML compiler compiles a page, it goes through 3 phases: Compile, Create Root Scope, and Link.

1. Compile Phase

2. Create Root Scope

3. Link Phase

Note that while the compile function is executed exactly once, the link function can be executed multiple times: once for each iteration in a repeater.

Example

The compilation process is best understood through example. Let's say that in your namespace my, you want to create a new DOM element , which should display a greeting.

If we want this HTML source:

<div ng:init="salutation='Hello'; name='World'">
  <my:greeter salutation="salutation" name="name"/>
</div>

To produce this DOM:

<div ng:init="salutation='Hello'; name='World'">
  <my:greeter salutation="salutation" name="name"/>
    <span class="salutation">Hello</span>
    <span class="name">World</span>!
  </my:greeter>
</div>

Write this widget definition (assuming you've already declared the my namespace in the page):

angular.widget('my:greeter', function(compileElement){
  var compiler = this;
  compileElement.css('display', 'block');
  var salutationExp = compileElement.attr('salutation');
  var nameExp = compileElement.attr('name');
  return function(linkElement){
    var salutationSpan = angular.element('<span class="salutation"></span');
    var nameSpan = angular.element('<span class="name"></span>');
    linkElement.append(salutationSpan);
    linkElement.append(compiler.text(' '));
    linkElement.append(nameSpan);
    linkElement.append(compiler.text('!'));
    this.$watch(salutationExp, function(value){
      salutationSpan.text(value);
    });
    this.$watch(nameExp, function(value){
    nameSpan.text(value);
    });
  };
});

Note: For more about widgets, see Widget.

Compilation process for this example

Here are the steps that the compiler goes through for the page that contains this widget definition:

Compile Phase

Link Phase

Compiler API

If you define your own widgets, markup, or directives, you need to access the compiler API. This section describes the methods on the compiler that you can call.

Note: As of 12 August 2010, these methods are subject to change.

Recall that the compile function's this is a reference to the compiler.