|
52 | 52 | * There are many different options for a directive.
|
53 | 53 | *
|
54 | 54 | * The difference resides in the return value of the factory function.
|
55 |
| - * You can either return a "Directive Definition Object" (see below) that defines the directive properties, |
56 |
| - * or just the `postLink` function (all other properties will have the default values). |
| 55 | + * You can either return a {@link $compile#directive-definition-object Directive Definition Object (see below)} |
| 56 | + * that defines the directive properties, or just the `postLink` function (all other properties will have |
| 57 | + * the default values). |
57 | 58 | *
|
58 | 59 | * <div class="alert alert-success">
|
59 | 60 | * **Best Practice:** It's recommended to use the "directive definition object" form.
|
|
117 | 118 | * });
|
118 | 119 | * ```
|
119 | 120 | *
|
| 121 | + * ### Life-cycle hooks |
| 122 | + * Directive controllers can provide the following methods that are called by Angular at points in the life-cycle of the |
| 123 | + * directive: |
| 124 | + * * `$onInit()` - Called on each controller after all the controllers on an element have been constructed and |
| 125 | + * had their bindings initialized (and before the pre & post linking functions for the directives on |
| 126 | + * this element). This is a good place to put initialization code for your controller. |
| 127 | + * * `$onChanges(changesObj)` - Called whenever one-way (`<`) or interpolation (`@`) bindings are updated. The |
| 128 | + * `changesObj` is a hash whose keys are the names of the bound properties that have changed, and the values are an |
| 129 | + * object of the form `{ currentValue, previousValue, isFirstChange() }`. Use this hook to trigger updates within a |
| 130 | + * component such as cloning the bound value to prevent accidental mutation of the outer value. |
| 131 | + * * `$doCheck()` - Called on each turn of the digest cycle. Provides an opportunity to detect and act on |
| 132 | + * changes. Any actions that you wish to take in response to the changes that you detect must be |
| 133 | + * invoked from this hook; implementing this has no effect on when `$onChanges` is called. For example, this hook |
| 134 | + * could be useful if you wish to perform a deep equality check, or to check a Date object, changes to which would not |
| 135 | + * be detected by Angular's change detector and thus not trigger `$onChanges`. This hook is invoked with no arguments; |
| 136 | + * if detecting changes, you must store the previous value(s) for comparison to the current values. |
| 137 | + * * `$onDestroy()` - Called on a controller when its containing scope is destroyed. Use this hook for releasing |
| 138 | + * external resources, watches and event handlers. Note that components have their `$onDestroy()` hooks called in |
| 139 | + * the same order as the `$scope.$broadcast` events are triggered, which is top down. This means that parent |
| 140 | + * components will have their `$onDestroy()` hook called before child components. |
| 141 | + * * `$postLink()` - Called after this controller's element and its children have been linked. Similar to the post-link |
| 142 | + * function this hook can be used to set up DOM event handlers and do direct DOM manipulation. |
| 143 | + * Note that child elements that contain `templateUrl` directives will not have been compiled and linked since |
| 144 | + * they are waiting for their template to load asynchronously and their own compilation and linking has been |
| 145 | + * suspended until that occurs. |
| 146 | + * |
| 147 | + * #### Comparison with Angular 2 life-cycle hooks |
| 148 | + * Angular 2 also uses life-cycle hooks for its components. While the Angular 1 life-cycle hooks are similar there are |
| 149 | + * some differences that you should be aware of, especially when it comes to moving your code from Angular 1 to Angular 2: |
| 150 | + * |
| 151 | + * * Angular 1 hooks are prefixed with `$`, such as `$onInit`. Angular 2 hooks are prefixed with `ng`, such as `ngOnInit`. |
| 152 | + * * Angular 1 hooks can be defined on the controller prototype or added to the controller inside its constructor. |
| 153 | + * In Angular 2 you can only define hooks on the prototype of the Component class. |
| 154 | + * * Due to the differences in change-detection, you may get many more calls to `$doCheck` in Angular 1 than you would to |
| 155 | + * `ngDoCheck` in Angular 2 |
| 156 | + * * Changes to the model inside `$doCheck` will trigger new turns of the digest loop, which will cause the changes to be |
| 157 | + * propagated throughout the application. |
| 158 | + * Angular 2 does not allow the `ngDoCheck` hook to trigger a change outside of the component. It will either throw an |
| 159 | + * error or do nothing depending upon the state of `enableProdMode()`. |
| 160 | + * |
| 161 | + * #### Life-cycle hook examples |
| 162 | + * |
| 163 | + * This example shows how you can check for mutations to a Date object even though the identity of the object |
| 164 | + * has not changed. |
| 165 | + * |
| 166 | + * <example name="doCheckDateExample" module="do-check-module"> |
| 167 | + * <file name="app.js"> |
| 168 | + * angular.module('do-check-module', []) |
| 169 | + * .component('app', { |
| 170 | + * template: |
| 171 | + * 'Month: <input ng-model="$ctrl.month" ng-change="$ctrl.updateDate()">' + |
| 172 | + * 'Date: {{ $ctrl.date }}' + |
| 173 | + * '<test date="$ctrl.date"></test>', |
| 174 | + * controller: function() { |
| 175 | + * this.date = new Date(); |
| 176 | + * this.month = this.date.getMonth(); |
| 177 | + * this.updateDate = function() { |
| 178 | + * this.date.setMonth(this.month); |
| 179 | + * }; |
| 180 | + * } |
| 181 | + * }) |
| 182 | + * .component('test', { |
| 183 | + * bindings: { date: '<' }, |
| 184 | + * template: |
| 185 | + * '<pre>{{ $ctrl.log | json }}</pre>', |
| 186 | + * controller: function() { |
| 187 | + * var previousValue; |
| 188 | + * this.log = []; |
| 189 | + * this.$doCheck = function() { |
| 190 | + * var currentValue = this.date && this.date.valueOf(); |
| 191 | + * if (previousValue !== currentValue) { |
| 192 | + * this.log.push('doCheck: date mutated: ' + this.date); |
| 193 | + * previousValue = currentValue; |
| 194 | + * } |
| 195 | + * }; |
| 196 | + * } |
| 197 | + * }); |
| 198 | + * </file> |
| 199 | + * <file name="index.html"> |
| 200 | + * <app></app> |
| 201 | + * </file> |
| 202 | + * </example> |
| 203 | + * |
| 204 | + * This example show how you might use `$doCheck` to trigger changes in your component's inputs even if the |
| 205 | + * actual identity of the component doesn't change. (Be aware that cloning and deep equality checks on large |
| 206 | + * arrays or objects can have a negative impact on your application performance) |
| 207 | + * |
| 208 | + * <example name="doCheckArrayExample" module="do-check-module"> |
| 209 | + * <file name="index.html"> |
| 210 | + * <div ng-init="items = []"> |
| 211 | + * <button ng-click="items.push(items.length)">Add Item</button> |
| 212 | + * <button ng-click="items = []">Reset Items</button> |
| 213 | + * <pre>{{ items }}</pre> |
| 214 | + * <test items="items"></test> |
| 215 | + * </div> |
| 216 | + * </file> |
| 217 | + * <file name="app.js"> |
| 218 | + * angular.module('do-check-module', []) |
| 219 | + * .component('test', { |
| 220 | + * bindings: { items: '<' }, |
| 221 | + * template: |
| 222 | + * '<pre>{{ $ctrl.log | json }}</pre>', |
| 223 | + * controller: function() { |
| 224 | + * this.log = []; |
| 225 | + * |
| 226 | + * this.$doCheck = function() { |
| 227 | + * if (this.items_ref !== this.items) { |
| 228 | + * this.log.push('doCheck: items changed'); |
| 229 | + * this.items_ref = this.items; |
| 230 | + * } |
| 231 | + * if (!angular.equals(this.items_clone, this.items)) { |
| 232 | + * this.log.push('doCheck: items mutated'); |
| 233 | + * this.items_clone = angular.copy(this.items); |
| 234 | + * } |
| 235 | + * }; |
| 236 | + * } |
| 237 | + * }); |
| 238 | + * </file> |
| 239 | + * </example> |
120 | 240 | *
|
121 | 241 | *
|
122 | 242 | * ### Directive Definition Object
|
|
292 | 412 | * The `$transclude` function also has a method on it, `$transclude.isSlotFilled(slotName)`, which returns
|
293 | 413 | * `true` if the specified slot contains content (i.e. one or more DOM nodes).
|
294 | 414 | *
|
295 |
| - * The controller can provide the following methods that act as life-cycle hooks: |
296 |
| - * * `$onInit()` - Called on each controller after all the controllers on an element have been constructed and |
297 |
| - * had their bindings initialized (and before the pre & post linking functions for the directives on |
298 |
| - * this element). This is a good place to put initialization code for your controller. |
299 |
| - * * `$onChanges(changesObj)` - Called whenever one-way (`<`) or interpolation (`@`) bindings are updated. The |
300 |
| - * `changesObj` is a hash whose keys are the names of the bound properties that have changed, and the values are an |
301 |
| - * object of the form `{ currentValue, previousValue, isFirstChange() }`. Use this hook to trigger updates within a |
302 |
| - * component such as cloning the bound value to prevent accidental mutation of the outer value. |
303 |
| - * * `$doCheck()` - Called on each turn of the digest cycle. Provides an opportunity to detect and act on |
304 |
| - * changes. Any actions that you wish to take in response to the changes that you detect must be |
305 |
| - * invoked from this hook; implementing this has no effect on when `$onChanges` is called. For example, this hook |
306 |
| - * could be useful if you wish to perform a deep equality check, or to check a Date object, changes to which would not |
307 |
| - * be detected by Angular's change detector and thus not trigger `$onChanges`. This hook is invoked with no arguments; |
308 |
| - * if detecting changes, you must store the previous value(s) for comparison to the current values. |
309 |
| - * * `$onDestroy()` - Called on a controller when its containing scope is destroyed. Use this hook for releasing |
310 |
| - * external resources, watches and event handlers. Note that components have their `$onDestroy()` hooks called in |
311 |
| - * the same order as the `$scope.$broadcast` events are triggered, which is top down. This means that parent |
312 |
| - * components will have their `$onDestroy()` hook called before child components. |
313 |
| - * * `$postLink()` - Called after this controller's element and its children have been linked. Similar to the post-link |
314 |
| - * function this hook can be used to set up DOM event handlers and do direct DOM manipulation. |
315 |
| - * Note that child elements that contain `templateUrl` directives will not have been compiled and linked since |
316 |
| - * they are waiting for their template to load asynchronously and their own compilation and linking has been |
317 |
| - * suspended until that occurs. |
318 |
| - * |
319 |
| - * ** $doCheck examples ** |
320 |
| - * |
321 |
| - * This example shows how you can check for mutations to a Date object even though the identity of the object |
322 |
| - * has not changed. |
323 |
| - * |
324 |
| - * <example name="doCheckDateExample" module="do-check-module"> |
325 |
| - * <file name="app.js"> |
326 |
| - * angular.module('do-check-module', []) |
327 |
| - * .component('app', { |
328 |
| - * template: |
329 |
| - * 'Month: <input ng-model="$ctrl.month" ng-change="$ctrl.updateDate()">' + |
330 |
| - * 'Date: {{ $ctrl.date }}' + |
331 |
| - * '<test date="$ctrl.date"></test>', |
332 |
| - * controller: function() { |
333 |
| - * this.date = new Date(); |
334 |
| - * this.month = this.date.getMonth(); |
335 |
| - * this.updateDate = function() { |
336 |
| - * this.date.setMonth(this.month); |
337 |
| - * }; |
338 |
| - * } |
339 |
| - * }) |
340 |
| - * .component('test', { |
341 |
| - * bindings: { date: '<' }, |
342 |
| - * template: |
343 |
| - * '<pre>{{ $ctrl.log | json }}</pre>', |
344 |
| - * controller: function() { |
345 |
| - * var previousValue; |
346 |
| - * this.log = []; |
347 |
| - * this.$doCheck = function() { |
348 |
| - * var currentValue = this.date && this.date.valueOf(); |
349 |
| - * if (previousValue !== currentValue) { |
350 |
| - * this.log.push('doCheck: date mutated: ' + this.date); |
351 |
| - * previousValue = currentValue; |
352 |
| - * } |
353 |
| - * }; |
354 |
| - * } |
355 |
| - * }); |
356 |
| - * </file> |
357 |
| - * <file name="index.html"> |
358 |
| - * <app></app> |
359 |
| - * </file> |
360 |
| - * </example> |
361 |
| - * |
362 |
| - * This example show how you might use `$doCheck` to trigger changes in your component's inputs even if the |
363 |
| - * actual identity of the component doesn't change. (Be aware that cloning and deep equality checks on large |
364 |
| - * arrays or objects can have a negative impact on your application performance) |
365 |
| - * |
366 |
| - * <example name="doCheckArrayExample" module="do-check-module"> |
367 |
| - * <file name="index.html"> |
368 |
| - * <div ng-init="items = []"> |
369 |
| - * <button ng-click="items.push(items.length)">Add Item</button> |
370 |
| - * <button ng-click="items = []">Reset Items</button> |
371 |
| - * <pre>{{ items }}</pre> |
372 |
| - * <test items="items"></test> |
373 |
| - * </div> |
374 |
| - * </file> |
375 |
| - * <file name="app.js"> |
376 |
| - * angular.module('do-check-module', []) |
377 |
| - * .component('test', { |
378 |
| - * bindings: { items: '<' }, |
379 |
| - * template: |
380 |
| - * '<pre>{{ $ctrl.log | json }}</pre>', |
381 |
| - * controller: function() { |
382 |
| - * this.log = []; |
383 |
| - * |
384 |
| - * this.$doCheck = function() { |
385 |
| - * if (this.items_ref !== this.items) { |
386 |
| - * this.log.push('doCheck: items changed'); |
387 |
| - * this.items_ref = this.items; |
388 |
| - * } |
389 |
| - * if (!angular.equals(this.items_clone, this.items)) { |
390 |
| - * this.log.push('doCheck: items mutated'); |
391 |
| - * this.items_clone = angular.copy(this.items); |
392 |
| - * } |
393 |
| - * }; |
394 |
| - * } |
395 |
| - * }); |
396 |
| - * </file> |
397 |
| - * </example> |
398 |
| - * |
399 | 415 | * #### `require`
|
400 | 416 | * Require another directive and inject its controller as the fourth argument to the linking function. The
|
401 | 417 | * `require` property can be a string, an array or an object:
|
|
0 commit comments