Directive Definition Object
不知道为什么这个我并没有想翻译过来的欲望,或许我并没有都看熟透,不好误人子弟,原版奉上。
Here's an example directive declared with a Directive Definition Object:
var myModule = angular.module(...);
myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
priority: 0,
template: '<div></div>', // or // function(tElement, tAttrs) { ... },
// or
// templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
transclude: false,
restrict: 'A',
templateNamespace: 'html',
scope: false,
controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
controllerAs: 'stringIdentifier',
bindToController: false,
require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) { ... },
post: function postLink(scope, iElement, iAttrs, controller) { ... }
}
// or
// return function postLink( ... ) { ... }
},
// or
// link: {
// pre: function preLink(scope, iElement, iAttrs, controller) { ... },
// post: function postLink(scope, iElement, iAttrs, controller) { ... }
// }
// or
// link: function postLink( ... ) { ... }
};
return directiveDefinitionObject;
});
Therefore the above can be simplified as:
var myModule = angular.module(...);
myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
link: function postLink(scope, iElement, iAttrs) { ... }
};
return directiveDefinitionObject;
// or
// return function postLink(scope, iElement, iAttrs) { ... }
});
Directive Definition Object
The directive definition object provides instructions to the compiler. The attributes are:
multiElement
When this property is set to true, the HTML compiler will collect DOM nodes between nodes with the attributes directive-name-start
and directive-name-end
, and group them together as the directive elements. It is recommended that this feature be used on directives which are not strictly behavioural (such as ngClick
), and which do not manipulate or replace child nodes (such as ngInclude
).
priority
When there are multiple directives defined on a single DOM element, sometimes it is necessary to specify the order in which the directives are applied. The priority
is used to sort the directives before their compile
functions get called. Priority is defined as a number. Directives with greater numerical priority
are compiled first. Pre-link functions are also run in priority order, but post-link functions are run in reverse order. The order of directives with the same priority is undefined. The default priority is 0
.
terminal
If set to true then the current priority
will be the last set of directives which will execute (any directives at the current priority will still execute as the order of execution on same priority
is undefined). Note that expressions and other directives used in the directive's template will also be excluded from execution.
scope
If set to true
, then a new scope will be created for this directive. If multiple directives on the same element request a new scope, only one new scope is created. The new scope rule does not apply for the root of the template since the root of the template always gets a new scope.
If set to {}
(object hash), then a new "isolate" scope is created. The 'isolate' scope differs from normal scope in that it does not prototypically inherit from the parent scope. This is useful when creating reusable components, which should not accidentally read or modify data in the parent scope.
The 'isolate' scope takes an object hash which defines a set of local scope properties derived from the parent scope. These local properties are useful for aliasing values for templates. Locals definition is a hash of local scope property to its source:
@
or@attr
- bind a local scope property to the value of DOM attribute. The result is always a string since DOM attributes are strings. If noattr
name is specified then the attribute name is assumed to be the same as the local name. Given<widget my-attr="hello {{name}}">
and widget definition ofscope: { localName:'@myAttr' }
, then widget scope propertylocalName
will reflect the interpolated value ofhello {{name}}
. As thename
attribute changes so will thelocalName
property on the widget scope. Thename
is read from the parent scope (not component scope).=
or=attr
- set up bi-directional binding between a local scope property and the parent scope property of name defined via the value of theattr
attribute. If noattr
name is specified then the attribute name is assumed to be the same as the local name. Given<widget my-attr="parentModel">
and widget definition ofscope: { localModel:'=myAttr' }
, then widget scope propertylocalModel
will reflect the value ofparentModel
on the parent scope. Any changes toparentModel
will be reflected inlocalModel
and any changes inlocalModel
will reflect inparentModel
. If the parent scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You can avoid this behavior using=?
or=?attr
in order to flag the property as optional. If you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use=*
or=*attr
(=*?
or=*?attr
if the property is optional).&
or&attr
- provides a way to execute an expression in the context of the parent scope. If noattr
name is specified then the attribute name is assumed to be the same as the local name. Given<widget my-attr="count = count + value">
and widget definition ofscope: { localFn:'&myAttr' }
, then isolate scope propertylocalFn
will point to a function wrapper for thecount = count + value
expression. Often it's desirable to pass data from the isolated scope via an expression to the parent scope, this can be done by passing a map of local variable names and values into the expression wrapper fn. For example, if the expression isincrement(amount)
then we can specify the amount value by calling thelocalFn
aslocalFn({amount: 22})
.
bindToController
When an isolate scope is used for a component (see above), and controllerAs
is used, bindToController: true
will allow a component to have its properties bound to the controller, rather than to scope. When the controller is instantiated, the initial values of the isolate scope bindings are already available.
controller
Controller constructor function. The controller is instantiated before the pre-linking phase and it is shared with other directives (seerequire
attribute). This allows the directives to communicate with each other and augment each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
$scope
- Current scope associated with the element$element
- Current element$attrs
- Current attributes object for the element$transclude
- A transclude linking function pre-bound to the correct transclusion scope:function([scope], cloneLinkingFn, futureParentElement)
.scope
: optional argument to override the scope.cloneLinkingFn
: optional argument to create clones of the original transcluded content.futureParentElement
:- defines the parent to which the
cloneLinkingFn
will add the cloned elements. - default:
$element.parent()
resp.$element
fortransclude:'element'
resp.transclude:true
. - only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements) and when the
cloneLinkinFn
is passed, as those elements need to created and cloned in a special way when they are defined outside their usual containers (e.g. like<svg>
). - See also the
directive.templateNamespace
property.
- defines the parent to which the
require
Require another directive and inject its controller as the fourth argument to the linking function. The require
takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the injected argument will be an array in corresponding order. If no such directive can be found, or if the directive does not have a controller, then an error is raised (unless no link function is specified, in which case error checking is skipped). The name can be prefixed with:
- (no prefix) - Locate the required controller on the current element. Throw an error if not found.
?
- Attempt to locate the required controller or passnull
to thelink
fn if not found.^
- Locate the required controller by searching the element and its parents. Throw an error if not found.^^
- Locate the required controller by searching the element's parents. Throw an error if not found.?^
- Attempt to locate the required controller by searching the element and its parents or passnull
to thelink
fn if not found.?^^
- Attempt to locate the required controller by searching the element's parents, or passnull
to thelink
fn if not found.
controllerAs
Identifier name for a reference to the controller in the directive's scope. This allows the controller to be referenced from the directive template. The directive needs to define a scope for this configuration to be used. Useful in the case when directive is used as component.
restrict
String of subset of EACM
which restricts the directive to a specific directive declaration style. If omitted, the defaults (elements and attributes) are used.
E
- Element name (default):<my-directive></my-directive>
A
- Attribute (default):<div my-directive="exp"></div>
C
- Class:<div class="my-directive: exp;"></div>
M
- Comment:<!-- directive: my-directive exp -->
templateNamespace
String representing the document type used by the markup in the template. AngularJS needs this information as those elements need to be created and cloned in a special way when they are defined outside their usual containers like <svg>
and <math>
.
html
- All root nodes in the template are HTML. Root nodes may also be top-level elements such as<svg>
or<math>
.svg
- The root nodes in the template are SVG elements (excluding<math>
).math
- The root nodes in the template are MathML elements (excluding<svg>
).
If no templateNamespace
is specified, then the namespace is considered to be html
.
template
HTML markup that may:
- Replace the contents of the directive's element (default).
- Replace the directive's element itself (if
replace
is true - DEPRECATED). - Wrap the contents of the directive's element (if
transclude
is true).
Value may be:
- A string. For example
<div red-on-hover>{{delete_str}}</div>
. - A function which takes two arguments
tElement
andtAttrs
(described in thecompile
function api below) and returns a string value.
templateUrl
This is similar to template
but the template is loaded from the specified URL, asynchronously.
Because template loading is asynchronous the compiler will suspend compilation of directives on that element for later when the template has been resolved. In the meantime it will continue to compile and link sibling and parent elements as though this element had not contained any directives.
The compiler does not suspend the entire compilation to wait for templates to be loaded because this would result in the whole app "stalling" until all templates are loaded asynchronously - even in the case when only one deeply nested directive has templateUrl
.
Template loading is asynchronous even if the template has been preloaded into the $templateCache
You can specify templateUrl
as a string representing the URL or as a function which takes two arguments tElement
and tAttrs
(described in the compile
function api below) and returns a string value representing the url. In either case, the template URL is passed through $sce.getTrustedResourceUrl.
replace
([DEPRECATED!], will be removed in next major release - i.e. v2.0)
specify what the template should replace. Defaults to false
.
true
- the template will replace the directive's element.false
- the template will replace the contents of the directive's element.
The replacement process migrates all of the attributes / classes from the old element to the new one. See the Directives Guide for an example.
There are very few scenarios where element replacement is required for the application function, the main one being reusable custom components that are used within SVG contexts (because SVG doesn't work with custom elements in the DOM tree).
transclude
Extract the contents of the element where the directive appears and make it available to the directive. The contents are compiled and provided to the directive as a transclusion function. See the Transclusion section below.
There are two kinds of transclusion depending upon whether you want to transclude just the contents of the directive's element or the entire element:
true
- transclude the content (i.e. the child nodes) of the directive's element.'element'
- transclude the whole of the directive's element including any directives on this element that defined at a lower priority than this directive. When used, thetemplate
property is ignored.
compile
function compile(tElement, tAttrs, transclude) { ... }
The compile function deals with transforming the template DOM. Since most directives do not do template transformation, it is not used often. The compile function takes the following arguments:
tElement
- template element - The element where the directive has been declared. It is safe to do template transformation on the element and child elements only.tAttrs
- template attributes - Normalized list of attributes declared on this element shared between all directive compile functions.transclude
- [DEPRECATED!] A transclude linking function:function(scope, cloneLinkingFn)
template
or templateUrl
declaration or manual compilation inside the compile function.transclude
function that is passed to the compile function is deprecated, as it e.g. does not know about the right outer scope. Please use the transclude function that is passed to the link function instead.A compile function can have a return value which can be either a function or an object.
returning a (post-link) function - is equivalent to registering the linking function via the
link
property of the config object when the compile function is empty.returning an object with function(s) registered via
pre
andpost
properties - allows you to control when a linking function should be called during the linking phase. See info about pre-linking and post-linking functions below.
link
This property is used only if the compile
property is not defined.
function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
The link function is responsible for registering DOM listeners as well as updating the DOM. It is executed after the template has been cloned. This is where most of the directive logic will be put.
scope
- Scope - The scope to be used by the directive for registering watches.iElement
- instance element - The element where the directive is to be used. It is safe to manipulate the children of the element only inpostLink
function since the children have already been linked.iAttrs
- instance attributes - Normalized list of attributes declared on this element shared between all directive linking functions.controller
- the directive's required controller instance(s) - Instances are shared among all directives, which allows the directives to use the controllers as a communication channel. The exact value depends on the directive'srequire
property:string
: the controller instancearray
: array of controller instances- no controller(s) required:
undefined
If a required controller cannot be found, and it is optional, the instance is
null
, otherwise the Missing Required Controller error is thrown.transcludeFn
- A transclude linking function pre-bound to the correct transclusion scope. This is the same as the$transclude
parameter of directive controllers, see there for details.function([scope], cloneLinkingFn, futureParentElement)
.
Pre-linking function
Executed before the child elements are linked. Not safe to do DOM transformation since the compiler linking function will fail to locate the correct elements for linking.
Post-linking function
Executed after the child elements are linked.
Note that child elements that contain templateUrl
directives will not have been compiled and linked since they are waiting for their template to load asynchronously and their own compilation and linking has been suspended until that occurs.
It is safe to do DOM transformation in the post-linking function on elements that are not waiting for their async templates to be resolved.
Transclusion
Transclusion is the process of extracting a collection of DOM element from one part of the DOM and copying them to another part of the DOM, while maintaining their connection to the original AngularJS scope from where they were taken.
Transclusion is used (often with ngTransclude
) to insert the original contents of a directive's element into a specified place in the template of the directive. The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded content has access to the properties on the scope from which it was taken, even if the directive has isolated scope. See the Directives Guide.
This makes it possible for the widget to have private state for its template, while the transcluded content has access to its originating scope.
Transclusion Functions
When a directive requests transclusion, the compiler extracts its contents and provides a transclusion function to the directive's link
function and controller
. This transclusion function is a special linking function that will return the compiled contents linked to a new transclusion scope.
ngTransclude
then you don't need to worry about this function, since ngTransclude will deal with it for us.If you want to manually control the insertion and removal of the transcluded content in your directive then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery object that contains the compiled DOM, which is linked to the correct transclusion scope.
When you call a transclusion function you can pass in a clone attach function. This function accepts two parameters,function(clone, scope) { ... }
, where the clone
is a fresh compiled copy of your transcluded content and the scope
is the newly created transclusion scope, to which the clone is bound.
cloneFn
(clone attach function) when you call a translude function since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.It is normal practice to attach your transcluded content (clone
) to the DOM inside your clone attach function:
var transcludedContent, transclusionScope;
$transclude(function(clone, scope) {
element.append(clone);
transcludedContent = clone;
transclusionScope = scope;
});
Later, if you want to remove the transcluded content from your DOM then you should also destroy the associated transclusion scope:
transcludedContent.remove();
transclusionScope.$destroy();
element.remove()
to remove it), then you are also responsible for calling $destroy
on the transclusion scope.The built-in DOM manipulation directives, such as ngIf
, ngSwitch
and ngRepeat
automatically destroy their transluded clones as necessary so you do not need to worry about this if you are simply using ngTransclude
to inject the transclusion into your directive.
Transclusion Scopes
When you call a transclude function it returns a DOM fragment that is pre-bound to a transclusion scope. This scope is special, in that it is a child of the directive's scope (and so gets destroyed when the directive's scope gets destroyed) but it inherits the properties of the scope from which it was taken.
For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look like this:
<div ng-app>
<div isolate>
<div transclusion>
</div>
</div>
</div>
The $parent
scope hierarchy will look like this:
- $rootScope
- isolate
- transclusion
but the scopes will inherit prototypically from different scopes to their $parent
.
- $rootScope
- transclusion
- isolate
Attributes
The Attributes object - passed as a parameter in the link()
or compile()
functions. It has a variety of uses.
accessing Normalized attribute names: Directives like 'ngBind' can be expressed in many ways: 'ng:bind', data-ng-bind
, or 'x-ng-bind'. the attributes object allows for normalized access to the attributes.
Directive inter-communication: All directives share the same instance of the attributes object which allows the directives to use the attributes object as inter directive communication.
Supports interpolation: Interpolation attributes are assigned to the attribute object allowing other directives to read the interpolated value.
Observing interpolated attributes: Use
$observe
to observe the value changes of attributes that contain interpolation (e.g.src="{{bar}}"
). Not only is this very efficient but it's also the only way to easily get the actual value because during the linking phase the interpolation hasn't been evaluated yet and so the value is at this time set toundefined
.
function linkingFn(scope, elm, attrs, ctrl) {
// get the attribute value
console.log(attrs.ngModel);
// change the attribute
attrs.$set('ngModel', 'new value');
// observe changes to interpolated attribute
attrs.$observe('ngModel', function(value) {
console.log('ngModel has changed value to ' + value);
});
}
Example
module.directive
. The example below is to illustrate how $compile
works.<script>
angular.module('compileExample', [], function($compileProvider) {
// configure new 'compile' directive by passing a directive
// factory function. The factory function injects the '$compile'
$compileProvider.directive('compile', function($compile) {
// directive factory creates a link function
return function(scope, element, attrs) {
scope.$watch(
function(scope) {
// watch the 'compile' expression for changes
return scope.$eval(attrs.compile);
},
function(value) {
// when the 'compile' expression changes
// assign it into the current DOM
element.html(value);
// compile the new DOM and link it to the current
// scope.
// NOTE: we only compile .childNodes so that
// we don't get into infinite loop compiling ourselves
$compile(element.contents())(scope);
}
);
};
});
})
.controller('GreeterController', ['$scope', function($scope) {
$scope.name = 'Angular';
$scope.html = 'Hello {{name}}';
}]);
</script>
<div ng-controller="GreeterController">
<input ng-model="name"> <br>
<textarea ng-model="html"></textarea> <br>
<div compile="html"></div>
</div>
Usage
$compile(element, transclude, maxPriority);
Arguments
Param | Type | Details |
---|---|---|
element | stringDOMElement |
Element or HTML string to compile into a template function. |
transclude | function(angular.Scope, cloneAttachFn=) |
function available to directives - DEPRECATED. Note: Passing a
transclude function to the $compile function is deprecated, as it e.g. will not use the right outer scope. Please pass the transclude function as a parentBoundTranscludeFn to the link function instead. |
maxPriority | number |
only apply directives lower than given priority (Only effects the root element(s), not their children) |
Returns
function(scope, cloneAttachFn=, options=) |
a link function which is used to bind template (a DOM element/tree) to a scope. Where:
Calling the linking function returns the element of the template. It is either the original element passed in, or the clone of the element if the After linking the view is not updated until after a call to $digest which typically is done by Angular automatically. If you need access to the bound view, there are two ways to do it:
For information on how the compiler works, see the Angular HTML Compiler section of the Developer Guide. |
Directive Definition Object的更多相关文章
- [AngularJS] Directive Definition Objects (DDO)
This function that we just set up is what's called a link function, and it's actually a very small p ...
- directive(指令里的)的compile,pre-link,post-link,link,transclude
The nitty-gritty of compile and link functions inside AngularJS directives The nitty-gritty of comp ...
- Scope Directive
---------------------------Scope-------------------------------- https://docs.angularjs.org/guide/sc ...
- Angular1.x directive(指令里的)的compile,pre-link,post-link,link,transclude
The nitty-gritty of compile and link functions inside AngularJS directives The nitty-gritty of comp ...
- Angular之 Scope和 Directive
---------------------------Scope-------------------------------- https://docs.angularjs.org/guide/sc ...
- angular源码分析:$compile服务——指令的编写
这一期中,我不会分析源码,只是翻译一下"https://docs.angularjs.org/api/ng/service/$compile",当然不是逐字逐句翻译,讲解指令应该如 ...
- AngularJs自定义指令详解(1) - restrict
下面所有例子都使用angular-1.3.16.下载地址:http://cdn.bootcss.com/angular.js/1.3.16/angular.min.js 既然AngularJs快要发布 ...
- [转贴]有关Angular 2.0的一切
对Angular 2.0的策略有疑问吗?就在这里提吧.在接下来的这篇文章里,我会解释Angular 2.0的主要特性区域,以及每个变化背后的动机.每个部分之后,我将提供自己在设计过程中的意见和见解,包 ...
- AngularJS Providers 详解
供应者(Providers) Each web application you build is composed of objects that collaborate to get stuff d ...
随机推荐
- 持续集成之戏说Check-in Dance
尽管Thoughtworks的首席科学家Martion folwer 为“持续集成 ” 下了定义,但由于自身背景与经历的不同,每个人对其都有不同的理解.从狭义上讲,持续集成可以认为是一种基于某种或者某 ...
- 应用hexo(rss插件)
使用RSS插件,来生成rss信息. 装载RSS插件 hexo根目录下进入git命令台 npm install hexo-generator-sitemap 启用RSS插件 hexo根目录下的 _con ...
- 修改weblogic jvm启动参数
进入: D:\Oracle\Middleware\user_projects\domains\base_domain\startWebLogic.cmd 在call 上一行增加: set USER_M ...
- js/bat批处理调用谷歌浏览器chrome批量打开网页测试web性能
批处理批量打开网页 其实用java就可以搞定,但是这么一个轻巧的测试,js或者bat批处理去一次性打开几百个网页测试一下页面没必要上java 两者的区别,js的话,只能打开多个浏览器实例,不方便查看效 ...
- PlatformTransactionManager
Spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactio ...
- jsoup技术抓取网页数据大全
jsoupNews Bugs Discussion Download API Reference Cookbook jsoup ? Cookbook ? Extracting data ? 使用选择器 ...
- 【C++基础之十五】内联函数
1.优点 为什么使用内联函数,而不使用宏定义,虽然宏本身采用的展开来替代函数调用的压栈出栈返回等操作,提高了代码的效率,但是会有两个问题: (1)边际效应 宏只是展开代码而已,所以在一些操作符的优先级 ...
- Delphi TdxComponentPrinter页头页脚的设定
TdxComponentPrinter页头页脚的设定 抄一段备忘.用程序控制也一样.如果是这样,那么 双击TdxComponentPrinter控件,在出现的窗口中,点击ADD,建立一个与TcxGri ...
- ink_test
- QQ空间自动发广告解决方法
最近空间好多人QQ都中了毒.每天我都有几十个好友刷空间话费.流量广告! QQ空间自动发广告的原因: 最近使用了刷赞或者其他QQ外挂软件(有些开发者或破解者会在这样的软件上留后门,请自己判断). 或者最 ...