为什么$ onInit()在角度材质对话框中不起作用?
背景:
在我正在开发的一个项目上,我们为系统的UI部分采用了Angular Material Design框架。我们将此与AngularJS 1.6.2和TypeScript 2.1.5结合使用。
我们一直在遇到的一条建议是使用AngularJS生命周期钩子,以便在AngularJS被弃用而支持Angular 2时做好准备。具体来说,引入了生命周期钩子,以便更容易升级,因为这些钩子钩 - 其中$onInit()
是一员 - 是纯粹基于组件的配置,它的角2
问题的一个主要特征的一部分:
我们发现,当你定义一个对话框控制器执行angular.IController
,并且具有用内容定义的$onInit()
...这些内容不被执行。
问题实施例打字稿:
// Bootstrap Angular to our example.
class App {
public constructor() {
angular.module('app', ['ui.router', 'ngMaterial']);
}
}
let app: App = new App();
// Set up routing for the example...
class RouteConfig {
constructor(
$stateProvider: angular.ui.IStateProvider,
$urlRouterProvider: angular.ui.IUrlRouterProvider,
$locationProvider: angular.ILocationProvider
){
$stateProvider.state('Main', {
url: '/Main',
templateUrl: 'app/Main.html',
controller: 'mainController'
});
$urlRouterProvider.otherwise('/Main');
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
}
}
angular.module('app').config(['$stateProvider', '$urlRouterProvider', '$locationProvider', RouteConfig]);
// Controller for the page that will launch the modal...
class MainController implements angular.IController {
public static $inject: string[] = ['$mdDialog'];
public constructor(public $mdDialog: angular.IDialogService) {
}
public $onInit(): void {
console.log('This works.');
}
public onButtonClick(): void {
this.$mdDialog.show({
controller: ModalController,
controllerAs: '$ctrl',
templateUrl: '/App/myModalTemplate.html', // Contents of modal not important.
parent: angular.element(document.body),
fullscreen: true
})
.then(() => console.log('Modal closed.'),
() => console.log('Modal cancelled.'));
}
}
angular.module('app').controller('mainController', MainController);
// Controller for the actual modal that should be triggering $onInit.
class ModalController implements angular.IController {
public static $inject: string[] = ['$mdDialog'];
public constructor(public $mdDialog: angular.IDialogService) {
alert('ModalController.ctor fired!');
}
public $onInit(): void {
// PROBLEM! This never actually executes.
alert('$onInit fired on modal!');
}
public ok(): void {
this.$mdDialog.hide();
}
}
angular.module('app').controller('modalController', ModalController);
应用程序/ main.html中
<div ng-controller="mainController as $ctrl"
md-content
layout-padding>
<h4>Modal Lifecycle Hook Problem Example</h4>
<md-button class="md-raised md-primary"
ng-click="$ctrl.onButtonClick()">
Show Modal
</md-button>
</div>
应用程序/ myModalTemplate.html:
<md-dialog>
<md-toolbar class="md-theme-light">
<h2>Modal</h2>
</md-toolbar>
<md-dialog-content class="md-padding">
Stuff, y'all.
</md-dialog-content>
<md-dialog-actions>
<md-button class="md-primary"
ng-click="$ctrl.ok()">
OK
</md>
</md-dialog-actions>
</md-dialog>
如果您设置了所有这些东西,并运行该项目,您将看到一个带有按钮的页面。当你点击按钮时,你只会得到一个警报 - 构造函数已经被触发。我在期待,你会得到两个警报:构造函数发起的消息,以及$onInit
发起的消息。
因此,这导致了我的...
问题:为什么说,如果材料设计对话控制器实现IController
,显然是生命周期挂钩不火?
在您的代码中有angular.module('app').controller('modalController', ModalController);
。我没有在代码中的任何地方看到modalController
,所以怀疑这个控制器实际上从未被触发。
这个答案没有帮助的原因是因为ModalController被定义为这样,并且被用作这样的。您会注意到我们在TypeScript中的$ mdDialog调用中使用了'ModalController'。这段代码实际上工作,并导致模态出现。问题是'$ onInit()'永远不会被触发。我能做些什么来使这个问题更容易混淆? –
我开始与AngularJS和我最近有同样的问题,在我的实习期间。我认为问题在于你的ModalController
没有被称为一个组件(它被称为$mdDialog
),所以它没有任何生命周期。
要解决此问题,您必须明确调用您的$onInit
方法。也许你可以在你的ModalController
构造函数中做到这一点。
我刚刚被这个问题困住了:$ onInit在“普通”控制器中调用,但不是mdDialog控制器。 你有没有想过? – LucasM
相关搜索:https://github.com/angular/material/issues/9259 – LucasM