使用Angular内容投影时,需要另一个升级组件的升级AngularJS组件找不到父控制器

时间:2018-07-09 15:11:16

标签: javascript angularjs angular typescript ng-upgrade

我正在尝试在我的应用程序的一个模块上为ngUpgrade进行PoC,但是我遇到了与AngularJS "root": "libs/my-lib", "sourceRoot": "libs/my-lib/src" 一起使用的包含/内容投影的问题。

假设有一个降级的Angular组件,定义如下:

requires

@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 {} 是需要父控制器的升级的AngularJS组件:

ajsButton

正常使用require: { ajsFilterCtrl: '^ajsFilter' } 可以很好地工作,但是在投影common-filter时像这样:

ajs-button

抛出此错误:

<common-filter> <ajs-button text="Inside of content projection"></ajs-button> </common-filter>

有什么办法解决吗?我知道我可以重写周围的类,但是许多其他应用程序都在使用它们,并且我需要能够逐渐升级这些应用程序。

工作示例:

https://stackblitz.com/edit/ngupgradestatic-playground-uvr14t

上面的摘录来自Unhandled Promise rejection: [$compile:ctreq] Controller 'ajsFilter', required by directive 'ajsButton', can't be found!index.html。这是一个(或多或少)基于更复杂组件的最小示例。出于性能原因,我将使用common-filter.component.ts方法。

1 个答案:

答案 0 :(得分:0)

维护者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