Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

docs(directive): Clarified and cleaned up directive guide #2888

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 30 additions & 39 deletions docs/content/guide/directive.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ api/ng.$rootScope.Scope#$digest digest} cycle. An example of interpolation is sh
here:

<pre>
<a href="img/{{username}}.jpg">Hello {{username}}!</a>
<a ng-href="img/{{username}}.jpg">Hello {{username}}!</a>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch!

</pre>


Expand Down Expand Up @@ -263,29 +263,38 @@ Here's an example directive declared with a Directive Definition Object:
myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
priority: 0,
template: '<div></div>',
templateUrl: 'directive.html',
template: '<div></div>', // or // function(tElement, tAttrs) { ... },
// or
// templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
replace: false,
transclude: false,
restrict: 'A',
scope: false,
controller: ["$scope", "$element", "$attrs", "$transclude", "otherInjectables",
function($scope, $element, $attrs, $transclude, otherInjectables) { ... }],
controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
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( ... ) { ... }
},
link: function postLink(scope, iElement, iAttrs) { ... }
// or
// link: {
// pre: function preLink(scope, iElement, iAttrs, controller) { ... },
// post: function postLink(scope, iElement, iAttrs, controller) { ... }
// }
// or
// link: function postLink( ... ) { ... }
};
return directiveDefinitionObject;
});
</pre>

In most cases you will not need such fine control and so the above can be simplified. You can still
return a Directive Definition Object, but only setting the 'compile' function property of the Object,
and rely on the default values for other properties.
return a Directive Definition Object, but only setting the 'link' function property of the Object,
and rely on the default values for other properties.

Therefore the above can be simplified as:

Expand All @@ -294,24 +303,11 @@ Therefore the above can be simplified as:

myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
compile: function compile(tElement, tAttrs) {
return function postLink(scope, iElement, iAttrs) { ... }
}
link: function postLink(scope, iElement, iAttrs) { ... }
};
return directiveDefinitionObject;
});
</pre>

Finally, most directives concern themselves only with instances, not with template transformations, allowing
further simplification.

Here we only define the postLink function:

<pre>
var myModule = angular.module(...);

myModule.directive('directiveName', function factory(injectables) {
return function postLink(scope, iElement, iAttrs) { ... }
// or
// return function postLink(scope, iElement, iAttrs) { ... }
});
</pre>

Expand Down Expand Up @@ -385,35 +381,30 @@ compiler}. The attributes are:
by calling the `localFn` as `localFn({amount: 22})`.

* `controller` - Controller constructor function. The controller is instantiated before the
pre-linking phase and it is shared with other directives if they request it by name (see
pre-linking phase and it is shared with other directives (see
`require` attribute). This allows the directives to communicate with each other and augment
each other's behavior. The controller is injectable with the following locals:
each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"bracket notation"? Do you mean "inline injection annotation"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I was worried people may not know what that means. I figure people see [ ... ] they think it's the 'bracket-way' of injecting.


* `$scope` - Current scope associated with the element
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why delete this phrase? You do need to "require" controllers by the name of the directive that creates it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to make the documentation more concise. I figured the docs need to be simplified. within the scope of this property, all you're doing is publicizing the function. I figured it's more important to talk about how to PULL IN this function when discussiong require.

* `$element` - Current element
* `$attrs` - Current attributes object for the element
* `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:
`function(cloneLinkingFn)`.

To avoid errors after minification the bracket notation should be used:

<pre>
controller: ['$scope', '$element', '$attrs', '$transclude', function($scope, $element, $attrs, $transclude) { ... }]
</pre>

* `require` - Require another controller be passed into current directive linking function. The
`require` takes a name of the directive controller to pass in. If no such controller can be
found an error is raised. The name can be prefixed with:
* `require` - Require another directive and inject it's _controller_ as the fourth argument to the linking function. The
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice rewording

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it should probably be 'another directive by name'

`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. The name can be prefixed with:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, I see you took "bracket notation" from here. Still even that is not consistently named, really.

* `?` - Don't raise an error. This makes the require dependency optional.
* `^` - Look for the controller on parent elements as well.
* `?` - Required dependency is optional. The parameter might be `null/undefined`.
* `^` - Look for the directive on parent/ancestor elements as well.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the ^? case should also be explicitly added here as (to me) it wasn't clear that both modifier could be specified.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would actually add a note above or below the bulleted items and not as an explicit item in the list. However re-reading my description, I think "Required dependency is optional" couldn't be any more confusing lol.



* `restrict` - String of subset of `EACM` which restricts the directive to a specific directive
declaration style. If omitted directives are allowed on attributes only.
declaration style. If omitted, the default (attributes only) is used.

* `E` - Element name: `<my-directive></my-directive>`
* `A` - Attribute: `<div my-directive="exp"></div>`
* `A` - Attribute (default): `<div my-directive="exp"></div>`
* `C` - Class: `<div class="my-directive: exp;"></div>`
* `M` - Comment: `<!-- directive: my-directive exp -->`

Expand Down