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

Commit 8bb1d98

Browse files
oliversalzburgSplaktar
authored andcommitted
fix(compiler): $onDestroy hook not called
Even though the $onInit lifecycle hook is fully supported, the $onDestroy hook isn't. This is unexpected for developers. This change introduces a listener for the $destroy event on the linked scope. See https://docs.angularjs.org/api/ng/type/$rootScope.Scope#event-$destroy This implementation closely resembles the AngularJS internal implementation of the lifecycle hook invokation behavior: https://github.com/angular/angular.js/blob/2b28c540ad7ebf4a9c3a6f108a9cb5b673d3712d/src/ng/compile.js#L3298-L3302 Fixes #11847
1 parent a3c533f commit 8bb1d98

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

src/core/services/compiler/compiler.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,15 @@ function MdCompilerProvider($compileProvider) {
436436
// Create the specified controller instance.
437437
var ctrl = self._createController(options, injectLocals, locals);
438438

439+
// Registering extra $destroy listeners should be avoided.
440+
// Only register the listener if the controller implements a $onDestroy hook.
441+
if (angular.isFunction(ctrl.$onDestroy)) {
442+
scope.$on('$destroy', function() {
443+
// Call the $onDestroy hook if it's present on the controller.
444+
angular.isFunction(ctrl.$onDestroy) && ctrl.$onDestroy();
445+
});
446+
}
447+
439448
// Unique identifier for AngularJS Route ngView controllers.
440449
element.data('$ngControllerController', ctrl);
441450
element.children().data('$ngControllerController', ctrl);

src/core/services/compiler/compiler.spec.js

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ describe('$mdCompiler service', function() {
195195
}
196196
});
197197
});
198-
198+
199199
function compileAndLink(options) {
200200
var compileData;
201201

@@ -482,4 +482,61 @@ describe('$mdCompiler service', function() {
482482
});
483483
});
484484

485+
describe('AngularJS 1.6+ lifecycle hooks', function() {
486+
var $mdCompiler, pageScope, $rootScope;
487+
488+
beforeEach(module('material.core'));
489+
490+
beforeEach(inject(function($injector) {
491+
$mdCompiler = $injector.get('$mdCompiler');
492+
$rootScope = $injector.get('$rootScope');
493+
pageScope = $rootScope.$new(false);
494+
}));
495+
496+
it('calls $onInit on initialization', function(done) {
497+
var passed = false;
498+
499+
class TestController {
500+
$onInit() { passed = true; }
501+
}
502+
503+
var compileResult = $mdCompiler.compile({
504+
template: '<span></span>',
505+
controller: TestController,
506+
controllerAs: 'vm',
507+
bindToController: true
508+
});
509+
510+
compileResult.then(function(compileOutput) {
511+
compileOutput.link(pageScope).scope();
512+
expect(passed).toBe(true);
513+
done();
514+
});
515+
516+
$rootScope.$apply();
517+
});
518+
519+
it('calls $onDestroy on destruction', function(done) {
520+
var passed = false;
521+
522+
class TestController {
523+
$onDestroy() { passed = true; }
524+
}
525+
526+
var compileResult = $mdCompiler.compile({
527+
template: '<span></span>',
528+
controller: TestController,
529+
controllerAs: 'vm',
530+
bindToController: true
531+
});
532+
533+
compileResult.then(function(compileOutput) {
534+
compileOutput.link(pageScope).scope().$destroy();
535+
expect(passed).toBe(true);
536+
done();
537+
});
538+
539+
$rootScope.$apply();
540+
});
541+
});
485542
});

0 commit comments

Comments
 (0)