# Directives Directives are classes which get instantiated as a respones to a particular DOM strcture. By controlling the DOM stracture, what directives are imported, and their selectors, the developer can use the [composition pattern](http://en.wikipedia.org/wiki/Object_composition) to get desirable application behavior. Directives are the cornerstone af Angular application. We use Directives to break complex problems into smaller more reusable components. Directives, allow the devolper turn HTML into a DSL and than controll the application assembly process. Angular applications do not have a main method. Instead they have a root Component. Dependency Injection than assembles the directives into a working Angular application. There are three different kinds of directives (described in mored detailed in later sections). 1. *Decorators*: can be placed on any DOM element and can be combined with other directives. 2. *Components*: Components have encapsulated view and can configure injectors. 3. *Instantiator*: Is responsible for adding or removing child views in parent view. (i.e. ng-repeat, ng-if) ## CSS Selectors Decorators are instantiated whenever the decorator CSS selector matches the DOM structure. Angular supports these CSS selector constructs: * Element name: `name` * Attribute: `[attribute]` * Attribute has value: `[attribute=value]` * Attribute contains value: `[attribute*=value]` * Class: `.class` * AND operation: `name[attribute]` * OR operation: `name,.class` Angular does not support these (and any CSS selector which crosses element boundries): * Descendant: `body div` * Direct descendant: `body > div` * Adjascent: `div + table` * Sibling: `div ~ table` * Wildcard: `*` * ID: `#id` * Pseudo selectors: `:pseudo` Given this DOM: `````` These CSS selectors will match: * `input`: Triggers whenever element name is `input`. * `[required]`: Triggers whenever element contains a required attribute. * `[type=text]`: Triggers whenever element contains attribute `type` whose value is `text`. * `.primary`: Triggers whenever element class contains `primary`. CSS Selectors can be combined: * `input[type=text]`: Triggers on element name `input` which is of `type` `text`. * `input[type=text], textarea`: triggers on element name `input` which is of `type` `text` or element name `textarea` ## Decorators The simplest kind of directive is a decorator. Directives are usefull for encapsulating behavior. * Multiple decorators can be placed on a single element. * Decorators do not introduce new evaluation context. * Decorators are registered througt the `@Decorator` meta-data annotation. Here is a triavial example of tooltip decorator. The directive will log a tooltip into the console on every time mouse enters a region: ``` @Decorator({ selector: '[tooltip]', // CSS Selector which triggers the decorator bind: { // List which properties need to be bound tooltip: 'text' // - DOM element tooltip property should be }, // mapped to the directive text property. event: { // List which events need to be mapped. mouseover: 'show' // - Invoke the show() method ever time } // the mouseover event is fired. }) class Form { // Directive controller class, instantiated // when CSS matches. text:string; // text property on the Decorator Controller. show(event) { // Show method which implements the show action. console.log(this.text); } } ``` Example of usage: ```Some text here.``` The developer of an applacation can now freely use the `tooltip` attribute wherever the behavior is needed. The code above has tought the browser a new reusable and declarative bahavior. Notice that databinding will work with this decorator with no further effort as show below. ```Some text here.``` ## Components Component is a directive which uses shadow DOM to create encapsulate visual behavior. Components are tipically used to create UI widgets or to break up the application into smaller components. * Only one component can be present per DOM element. * Components CSS selectors usualy trigger on element names. (Best practice) * Component has its own shadow view which is attached to the element as a Shadow DOM. * Shadow view context is the component instance. (i.e. template expressions are evaluated against the component instance.) >> TODO(misko): Configuring the injector Example of a component: ``` @Component({ | Component annotation selector: 'pane', | CSS selector on element bind: { | List which property need to be bound 'title': 'title', | - title mapped to component title 'open': 'open' | - open mapped to component title }, | template: new TemplateConfig({ | Define template to be used with component url: 'pane.html', | - URL of template HTML cssUrl: 'pane.css' | - URL of CSS to be used with the component }) | }) | class Pane { | Component controller class title:string; | - title property open:boolean; constructor() { this.title = ''; this.open = true; } // Public API toggle() => this.open = !this.open; open() => this.open = true; close() => this.open = false; } ``` `pane.html`: ```

{{title}}

``` `pane.css`: ``` .outter, .inner { border: 1px solid blue;} .h1 {background-color: blue;} ``` Example of usage: ``` Some text to wrap. ``` ## Instantiator Instantiator is a directive which can controll instantiation of child views which are then inserted into the DOM. (Examples are `ng-if` and `ng-repeat`.) * Instantiators can only be placed on `