为什么 $onInit() 不在 angular material 对话框中触发?
Why doesn't $onInit() fire in an angular material dialog?
背景:
在我正在进行的一个项目中,我们为系统的 UI 部分采用了 Angular Material 设计框架。我们将其与 AngularJS 1.6.2 和 TypeScript 2.1.5 结合使用。
我们不断遇到的一条建议是使用 AngularJS 生命周期挂钩,以备不时 AngularJS 被弃用,取而代之的是 Angular 2. 特别是, 引入了生命周期挂钩以使其更容易升级,因为这些挂钩 - 其中 $onInit()
是成员 - 是纯粹基于组件的设置的一部分,这是 Angular 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);
app/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>
app/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
触发消息。
因此,这导致了我的...
问题: 为什么如果 Material 设计对话框控制器实现 IController
,显然生命周期挂钩不会触发?
在您的代码中有 angular.module('app').controller('modalController', ModalController);
。我在你的代码中没有看到 modalController
所以怀疑这个控制器实际上从未被触发过。
我从 AngularJS 开始,我最近在实习期间遇到了同样的问题。我认为问题是你的 ModalController
没有被称为组件(它被称为 $mdDialog
)所以它没有任何生命周期。
要解决此问题,您必须显式调用 $onInit
方法。也许您可以在 ModalController
构造函数中执行此操作。
背景:
在我正在进行的一个项目中,我们为系统的 UI 部分采用了 Angular Material 设计框架。我们将其与 AngularJS 1.6.2 和 TypeScript 2.1.5 结合使用。
我们不断遇到的一条建议是使用 AngularJS 生命周期挂钩,以备不时 AngularJS 被弃用,取而代之的是 Angular 2. 特别是, 引入了生命周期挂钩以使其更容易升级,因为这些挂钩 - 其中 $onInit()
是成员 - 是纯粹基于组件的设置的一部分,这是 Angular 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);
app/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>
app/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
触发消息。
因此,这导致了我的...
问题: 为什么如果 Material 设计对话框控制器实现 IController
,显然生命周期挂钩不会触发?
在您的代码中有 angular.module('app').controller('modalController', ModalController);
。我在你的代码中没有看到 modalController
所以怀疑这个控制器实际上从未被触发过。
我从 AngularJS 开始,我最近在实习期间遇到了同样的问题。我认为问题是你的 ModalController
没有被称为组件(它被称为 $mdDialog
)所以它没有任何生命周期。
要解决此问题,您必须显式调用 $onInit
方法。也许您可以在 ModalController
构造函数中执行此操作。