diff --git a/src/core/services/compiler/compiler.js b/src/core/services/compiler/compiler.js index abe73665dd..e5b7bc45a5 100644 --- a/src/core/services/compiler/compiler.js +++ b/src/core/services/compiler/compiler.js @@ -436,6 +436,15 @@ function MdCompilerProvider($compileProvider) { // Create the specified controller instance. var ctrl = self._createController(options, injectLocals, locals); + // Registering extra $destroy listeners should be avoided. + // Only register the listener if the controller implements a $onDestroy hook. + if (angular.isFunction(ctrl.$onDestroy)) { + scope.$on('$destroy', function() { + // Call the $onDestroy hook if it's present on the controller. + angular.isFunction(ctrl.$onDestroy) && ctrl.$onDestroy(); + }); + } + // Unique identifier for AngularJS Route ngView controllers. element.data('$ngControllerController', ctrl); element.children().data('$ngControllerController', ctrl); diff --git a/src/core/services/compiler/compiler.spec.js b/src/core/services/compiler/compiler.spec.js index df5148294d..88b5234dd0 100644 --- a/src/core/services/compiler/compiler.spec.js +++ b/src/core/services/compiler/compiler.spec.js @@ -195,7 +195,7 @@ describe('$mdCompiler service', function() { } }); }); - + function compileAndLink(options) { var compileData; @@ -482,4 +482,61 @@ describe('$mdCompiler service', function() { }); }); + describe('AngularJS 1.6+ lifecycle hooks', function() { + var $mdCompiler, pageScope, $rootScope; + + beforeEach(module('material.core')); + + beforeEach(inject(function($injector) { + $mdCompiler = $injector.get('$mdCompiler'); + $rootScope = $injector.get('$rootScope'); + pageScope = $rootScope.$new(false); + })); + + it('calls $onInit on initialization', function(done) { + var passed = false; + + class TestController { + $onInit() { passed = true; } + } + + var compileResult = $mdCompiler.compile({ + template: '', + controller: TestController, + controllerAs: 'vm', + bindToController: true + }); + + compileResult.then(function(compileOutput) { + compileOutput.link(pageScope).scope(); + expect(passed).toBe(true); + done(); + }); + + $rootScope.$apply(); + }); + + it('calls $onDestroy on destruction', function(done) { + var passed = false; + + class TestController { + $onDestroy() { passed = true; } + } + + var compileResult = $mdCompiler.compile({ + template: '', + controller: TestController, + controllerAs: 'vm', + bindToController: true + }); + + compileResult.then(function(compileOutput) { + compileOutput.link(pageScope).scope().$destroy(); + expect(passed).toBe(true); + done(); + }); + + $rootScope.$apply(); + }); + }); });