升级的 AngularJS 组件需要另一个升级的组件,在使用 Angular 内容投影时找不到父控制器
Upgraded AngularJS component which requires another upgraded component can't find the parent controller when using Angular content projection
我正在尝试在我的应用程序的一个模块上为 ngUpgrade 做一个 PoC,我 运行 遇到 transclusion/content 投影和 AngularJS requires
.
假设有一个降级的 Angular 组件定义如下:
@Component({
selector: 'common-filter',
template: `
<ajs-filter>
<div>Common Filter</div>
<ajs-button text="Outside of content projection"></ajs-button>
<ng-content></ng-content>
</ajs-filter>
})
export class CommonFilter {}
ajsButton
是升级后的AngularJS组件,需要父控制器:
require: {
ajsFilterCtrl: '^ajsFilter'
}
common-filter
的正常使用效果非常好,但是当投影 ajs-button
时,例如:
<common-filter>
<ajs-button text="Inside of content projection"></ajs-button>
</common-filter>
抛出此错误:
Unhandled Promise rejection: [$compile:ctreq] Controller 'ajsFilter', required by directive 'ajsButton', can't be found!
有什么办法解决这个问题吗?我知道我可以重写周围的类,但是很多其他应用程序都在使用它们,我需要能够逐步升级这些应用程序。
工作示例:
https://stackblitz.com/edit/ngupgradestatic-playground-uvr14t
以上片段来自 index.html
和 common-filter.component.ts
。这是一个(或多或少)基于更复杂组件的最小示例。出于性能原因,我将采用 downgradeModule
方法。
维护者 gkalpak 在我为此发布的 Github 问题中提供了解决此问题的方法:
https://github.com/angular/angular/issues/24846#issuecomment-404448494
简而言之,这是不同控制器初始化顺序的问题。
要绕过它,您可以使父控制器 require
可选,然后使用 setTimeout
等待父控制器初始化:
this.$onInit = () => {
this.requireAjsFilterCtrl().then(() => console.log('!', !!this.ajsFilterCtrl));
}
this.requireAjsFilterCtrl = () => {
return new Promise(resolve => {
setTimeout(() => {
this.ajsFilterCtrl = this.ajsFilterCtrl || $element.controller('ajsFilter');
resolve(this.ajsFilterCtrl);
});
});
};
可以在此处查看解决方法:
https://stackblitz.com/edit/ngupgradestatic-playground-a6zkwb
我正在尝试在我的应用程序的一个模块上为 ngUpgrade 做一个 PoC,我 运行 遇到 transclusion/content 投影和 AngularJS requires
.
假设有一个降级的 Angular 组件定义如下:
@Component({
selector: 'common-filter',
template: `
<ajs-filter>
<div>Common Filter</div>
<ajs-button text="Outside of content projection"></ajs-button>
<ng-content></ng-content>
</ajs-filter>
})
export class CommonFilter {}
ajsButton
是升级后的AngularJS组件,需要父控制器:
require: {
ajsFilterCtrl: '^ajsFilter'
}
common-filter
的正常使用效果非常好,但是当投影 ajs-button
时,例如:
<common-filter>
<ajs-button text="Inside of content projection"></ajs-button>
</common-filter>
抛出此错误:
Unhandled Promise rejection: [$compile:ctreq] Controller 'ajsFilter', required by directive 'ajsButton', can't be found!
有什么办法解决这个问题吗?我知道我可以重写周围的类,但是很多其他应用程序都在使用它们,我需要能够逐步升级这些应用程序。
工作示例:
https://stackblitz.com/edit/ngupgradestatic-playground-uvr14t
以上片段来自 index.html
和 common-filter.component.ts
。这是一个(或多或少)基于更复杂组件的最小示例。出于性能原因,我将采用 downgradeModule
方法。
维护者 gkalpak 在我为此发布的 Github 问题中提供了解决此问题的方法: https://github.com/angular/angular/issues/24846#issuecomment-404448494
简而言之,这是不同控制器初始化顺序的问题。
要绕过它,您可以使父控制器 require
可选,然后使用 setTimeout
等待父控制器初始化:
this.$onInit = () => {
this.requireAjsFilterCtrl().then(() => console.log('!', !!this.ajsFilterCtrl));
}
this.requireAjsFilterCtrl = () => {
return new Promise(resolve => {
setTimeout(() => {
this.ajsFilterCtrl = this.ajsFilterCtrl || $element.controller('ajsFilter');
resolve(this.ajsFilterCtrl);
});
});
};
可以在此处查看解决方法: https://stackblitz.com/edit/ngupgradestatic-playground-a6zkwb