DailyJS

AngularJS: About Those Custom Attributes...

Alex R. Young

Subscribe

@dailyjs

Facebook

Google+

tutorials mvc angularjs

AngularJS: About Those Custom Attributes...

Posted by Alex R. Young on .
Featured

tutorials mvc angularjs

AngularJS: About Those Custom Attributes...

Posted by Alex R. Young on .

The first thing I noticed on the AngularJS homepage was the use of a non-standard attribute, ng-app:

<div ng-app>  
  <div>
    <label>Name:</label>
    <input type="text" ng-model="yourName" placeholder="Enter a name here">
    <hr>
    <h1>Hello {{yourName}}!</h1>
  </div>
</div>  

Suspicious as I am, I wanted to look into this further. Running a more complete HTML5 example through the w3.org validator shows errors for each ng- attribute:

  • Attribute ng-app not allowed on element div at this point.
  • Attribute ng-model not allowed on element div at this point.

Earlier HTML specifications state that unrecognised attributes should be ignored, so this should be safe enough -- clients will generally ignore the unrecognised attribute and JavaScript can handle it as required by AngularJS.

The AngularJS developers have gone a step further to quell fears of rogue attributes causing unexpected issues: it now transparently supports data- prefixed attributes. That means the previous example could be written with data-ng-app and it would still work. I tried it out and found that it even copes with mixed attribute styles.

Knockout

Unlike AngularJS, Knockout embraced data- attributes from the beginning. The documentation even clarifies the use of data attributes:

The data-bind attribute isn't native to HTML, though it is perfectly OK (it's strictly compliant in HTML 5, and causes no problems with HTML 4 even though a validator will point out that it's an unrecognized attribute). But since the browser doesn't know what it means, you need to activate Knockout to make it take effect.

Although AngularJS now fully supports this approach, using custom attributes may have hurt early adoption.

Directives

The underlying mechanism that AngularJS uses to support multiple attribute prefixes is Directives, which according to the documentation turns HTML into a "declarative domain specific language". You may have noticed that AngularJS templates are HTML -- this contrasts with many other frameworks that use a string-based template system. Since templates are HTML, the entire page can be loaded and parsed by the browser. The resulting DOM is traversed by AngularJS's compiler to find directives. The resulting set of directives is associated with DOM elements and prioritised. Each directive has a compile method, which can modify the DOM, and generates a link function.

Links are live bindings, and splitting compilation into stages like this means AngularJS can do a certain amount of work before repeatedly rendering sets of elements. The example in the documentation is rendering lots of list elements:

The result of of the li element compilation is a linking function which contains all of the directives contained in the li element, ready to be attached to a specific clone of the li element.

Conclusion

Although AngularJS may have been treated with some trepidation due to the adoption of non-standard HTML attributes, the authors have identified this and it's possible to write applications that will validate. The "declarative domain specific language" concept is definitely interesting, and the two-stage compilation process has some advantages over other schemes that I've seen.