by Nicholas Boll
If you use Angular, you already use Directives (ex: ng-model)
Angular gives you many powerful directives
jQuery, right?
restrict
CSS classes? Comments?!
Mostly used internal for directives like ng-repeat
This is because the Browser parses HTML into DOM and then Angular gets to it
Ex: my-directive
creates a td
I don't suggest using classes as directives. CSS classes are style-hooks and not obvious that behavior is being added.
IE8 can't parse Element directives without the help of the document.createElement
hack. Stick with attribute
directives for IE8 support.
priority
Number
Tells the compiler
what order to process directives
Higher numbers get processed first
terminal
Boolean
True means no further compiling will be done of lower priority or child directives
scope
Boolean
or Object
hashtrue
for a new scopeObject
hash for an isolate
scope=
@
hello {{name}}
&
controller
require
String
or String[]
(no prefix)
is current element, ^
is parent and ?
means optionaltemplate
String
or Function(tElement, tAttr)
HTML
templateUrl
String
template
, but loaded from URL$templateCache
for prod and testingreplace
true
to replace the current element with template (must be 1 root element in template)false
to replace contents of current elementtransclude
Boolean
ng-transclude
and an isolate scope
Think of a widget where your template is a picture frame and ng-transclude
is the place where the picture goes
This content is transcluded like a picture!
{{ message }}
link
Function (scope, iElement, iAttributes, controller, transcludeFn)
Object { preLink: Function, postLink: Function}
function
, it is a postLink
functioncompile
function is needed (most of the time)controller
is a reference or array of references to required controllers (including controller of the directive if applicable)transclude
is true, transcludeFn
will be a pre-bound transclude function for cloning (ng-repeat
)preLink
controller
scope
, but not DOM
form
and ngInit
postLink
DOM
listeners and manipulate DOM
compile
Function (tElement, tAttributes)
link
function or objectscope
compile
vs link
Think of underscore
or Handlebar
templates: you compile a string into a template function, then call the template function with data.
Handlebars:
var template = Handlebars.compile('{{ title }}');
var html = template({ title: 'My Title' });
Angular:
scope.title = 'My Title';
var linkFn = $compile('{{ title }}');
linkFn(scope);
compile
vs link
compile
is added for performance. It is only run once while link is run for each clone
scope.$on('$destroy', ...
ng-grid
angular-table
angular.module('presentation').directive('nbTooltip', function ($document, $compile) {
return {
scope: true,
link: function (scope, element, attrs) {
var tooltip = null;
var tooltipLinker = $compile('{{ text }}');
function showTooltip (event) {
tooltip = tooltipLinker(scope);
scope.text = attrs.nbTooltip;
scope.$digest();
tooltip.css({
top: event.y + 5 + 'px',
left: event.x + 5 + 'px'
});
$document.find('body').append(tooltip);
}
function hideTooltip (event) {
tooltip.remove();
}
element.on('mouseover', showTooltip);
element.on('mouseout', hideTooltip);
scope.$on('$destroy', function () {
element.off('mouseover', showTooltip);
element.off('mouseout', hideTooltip);
});
}
};
});
$compile service
(used when compiling bootstrapped apps)$destroy
eventThe directive used to power the examples in this presentation
angular.module('directives.example', []).directive('nbExample', function ($compile) {
return {
// create isolate scopes for examples
scope: {},
// Only match to element or attribute
restrict: 'EA',
// don't process any other directive
terminal: true,
// priority higher than other directives
priority: 1000,
// compile function - this will return a linking function
compile: function (templateElement, templateAttributes) {
/* compile the template. This will return a function that will create
* real DOM within a scope - kind of like underscore templates return
* a function that will operate on data
* We need more control for this template than providing a template
* attribute to the directive
*/
var template = $compile('Example:
Output:
');
// Get the contents of the directive as a string for later use
var example = templateElement.html();
// Remove leading whitespaces and replace with a single return per line
var leadingWhitespace = example.match(/^\s+/)[0];
example = example.replace(new RegExp(leadingWhitespace, 'g'), "\n").replace("\n", '');
templateElement.empty();
// return the linking function
return function link (scope, element, attrs) {
// evaluate the template using a scope
var html = angular.element(template(scope));
html.find('code').addClass(attrs.language).text(example);
html.find('div').append($compile(example)(scope));
element.append(html);
}
}
};
});