Skip to content

Commit 50b0c1a

Browse files
feat($compile): call $ngOnInit on directive controllers after controller construction
This enables option three of angular#13510 (comment) by allowing the creator of directive controllers using ES6 classes to have a hook that is called when the bindings are definitely available. Moreover this will help solve the problem of accessing `require`d controllers from controller instances without resorting to wiring up in a `link` function. See angular#5893
1 parent 95b3e1c commit 50b0c1a

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

src/ng/compile.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -1072,7 +1072,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
10721072
transclude: options.transclude,
10731073
scope: {},
10741074
bindToController: options.bindings || {},
1075-
restrict: 'E'
1075+
restrict: 'E',
1076+
require: options.require
10761077
};
10771078
}
10781079

@@ -2388,6 +2389,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
23882389
}
23892390
}
23902391

2392+
// Trigger the `$onInit` method on all controllers that have one
2393+
forEach(elementControllers, function(controller) {
2394+
if (isFunction(controller.instance.$onInit)) {
2395+
controller.instance.$onInit();
2396+
}
2397+
});
2398+
23912399
// PRELINKING
23922400
for (i = 0, ii = preLinkFns.length; i < ii; i++) {
23932401
linkFn = preLinkFns[i];

test/ng/compileSpec.js

+26
Original file line numberDiff line numberDiff line change
@@ -4929,6 +4929,32 @@ describe('$compile', function() {
49294929
});
49304930
});
49314931

4932+
it('should call `controller.$onInit`, if provided after all the controllers have been constructed', function() {
4933+
4934+
function Controller1($element) { this.id = 1; this.element = $element; }
4935+
Controller1.prototype.$onInit = jasmine.createSpy('$onInit').andCallFake(function() {
4936+
expect(this.element.controller('d1').id).toEqual(1);
4937+
expect(this.element.controller('d2').id).toEqual(2);
4938+
});
4939+
4940+
function Controller2($element) { this.id = 2; this.element = $element; }
4941+
Controller2.prototype.$onInit = jasmine.createSpy('$onInit').andCallFake(function() {
4942+
expect(this.element.controller('d1').id).toEqual(1);
4943+
expect(this.element.controller('d2').id).toEqual(2);
4944+
});
4945+
4946+
angular.module('my', [])
4947+
.directive('d1', function() { return { controller: Controller1 }; })
4948+
.directive('d2', function() { return { controller: Controller2 }; });
4949+
4950+
module('my');
4951+
inject(function($compile, $rootScope) {
4952+
element = $compile('<div d1 d2></div>')($rootScope);
4953+
expect(Controller1.prototype.$onInit).toHaveBeenCalledOnce();
4954+
expect(Controller2.prototype.$onInit).toHaveBeenCalledOnce();
4955+
});
4956+
});
4957+
49324958
describe('should not overwrite @-bound property each digest when not present', function() {
49334959
it('when creating new scope', function() {
49344960
module(function($compileProvider) {

0 commit comments

Comments
 (0)