Directives allow you to create reusable snippets of HTML.
The syntax for using directives is the same as classic HTML, although directives will normally contain at least one "-" character (i.e. ng-model, ng-if, ng-show, etc.)
Some useful built-in Directives
ngShow / ngHide
Given an expression, these directives will show or hide it from the display if their assigned expression evaluates to true.
<span class="label label-danger" ng-show="services.length === 0">No services to show!</span> <span class="label label-danger" ng-hide="services.length === 0">We have available services!</span>
ngIf
Render a section of HTML only if a particular expression evaluates to true.
This is like ngShow, except that instead of hiding the drawn output, the output is never added to the DOM.
<input type="checkbox" ng-model="showBtn"> <div ng-if="showBtn"> <button class="btn btn-success">You found me!</button> </div>
ngRepeat
Render a section of HTML once for every item in a list. This can be very useful for creating lists of options and grids of tabular data.
<table class="table table-striped table-condensed table-hover" ng-hide="disabled || (services | filter : serviceSearchQuery).length === 0"> <tbody> <tr ng-repeat="service in services"> <td>{{ service.label }}</td> <td>{{ service.count }}</td> </tr> </tbody> </table>
ngModel
From most input fields, it is possible to specify a "model" which tells angular the name of the variable in which the input should write back its value.
This allows for powerful two-way data binding, seen below:
<!-- The value written into this input can be accessed in the controller as "$scope.name" --> <p>Name : <input type="text" ng-model="name"></p> <!-- "{{ expression }}" means "evaluate this expression and re-evaluate it if it or any of its inputs change" --> <h1>Hello {{name}}</h1>
NOTE: "Two-way" refers to the ways in which the user can update this binding:
- User changes input, which writes back to the scope variable
- User changes scope variable, which writes back to the input field
ngInclude / ngSrc / ngController
Instead of specifying all your markup as one giant file, you can use the following syntax to substitute another view / scope in for any element:
<!-- ngInclude and ngSrc tells angular that this div should display markup not found in this file. --> <!-- ngController tells Angular which scope to bind against for this partial view. --> <div ng-include src="'/app/shared/navbar.html'" ng-controller="NavbarController" ></div>
ngMouseover / ngMouseenter / ngMouseleave
Perform the given function when the mouse cursor enters, leaves, or hovers over a particular element.
WARNING: These directives are not mobile-friendly, as there is no mouse cursor.
ngMouseup / ngMousedown / ngClick
Angular-ized version of the classic "click" behavior, these directives will perform a given function when the mouse cursor is pressed or released.
<button type="submit" ng-click="login()" class="btn btn-default"> Login </button>
ngStyle / ngClass
Sometimes, we want to style particular elements based on values in their scope; enter ngStyle and ngClass.
These amazing directives may seem complicated at first, but they are extremely powerful.
Using ngStyle, you can apply particular style values that change with the values of your scope!
The same syntax can also be used for ngClass. For example:
<!-- The value of ng-style / ng-class is an object specifying labels and an expression representing when they should be applied. --> <button ng-style="{ 'color': ngStyleClicked ? 'green' : 'red' }" ng-click="ngStyleClicked = true;"> Using ngStyle </button> <button ng-class="{ 'btn-danger': !ngClassClicked, 'btn-success': ngClassClicked }" ng-click="ngClassClicked = true;"> Using ngClass </button>
ngDisabled
Want to disable an element to prevent the user from clicking or inputting to them under certain conditions?
Feeding ngDisabled a function will disable the specified element whenever that function returns true.
<button type="submit" ng-disabled="true" class="btn btn-default"> Can't click me! </button>
Creating Custom Directives
AngularJS also allows for the user to define their own directives! These directives can define new HTML elements, attributes, and classes!
There are even methods for parsing comments into new HTML, allowing for "annotations" in JavaScript.
Defining a custom directive may seem daunting at first, but I promise it's not that bad and well worth the effort for reusable HTML.
Let's take a look at a simple custom directive:
var mainApp = angular.module("mainApp", []); //Create a directive, first parameter is the html element to be attached. //We are attaching student html tag. //This directive will be activated as soon as any student element is encountered in html mainApp.directive('student', function() { //define the directive object var directive = {}; //restrict = E, signifies that directive is Element directive directive.restrict = 'E'; //template replaces the complete element with its text. directive.template = "Student: <b>{{student.name}}</b> , Roll No: <b>{{student.rollno}}</b>"; //scope is used to distinguish each student element based on criteria. directive.scope = { student : "=name" } //compile is called during application initialization. AngularJS calls it once when html page is loaded. directive.compile = function(element, attributes) { element.css("border", "1px solid #cccccc"); //linkFunction is linked with each element with scope to get the element specific data. var linkFunction = function($scope, element, attributes) { element.html("Student: <b>"+$scope.student.name +"</b> , Roll No: <b>"+$scope.student.rollno+"</b><br/>"); element.css("background-color", "#ff00ff"); } return linkFunction; } return directive; });
We can then use our custom 'E' directive as an HTML element, as follows:
<student name="Student A"></student><br/> <student name="Student B"></student>
Directive Types
The directive.restrict member above tells Angular which type or types our custom directive should match.
The different types include:
- E: Matches a tag name
- A: Matches an attribute name
- C: Matches a class name
- M: Matches a comment
<my-dir></my-dir> <span my-dir="exp"></span> <!-- directive: my-dir exp --> <span class="my-dir: exp;"></span>
These types can even be combined to create very flexible and reusable view aspects.
For example, the following restriction would allow our directive to affect attribute name or element name or class name, in that order:
directive.restrict = 'AEC';