0

我正在尝试在我的应用程序的一个模块上为 ngUpgrade 做一个 PoC,并且我遇到了与 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.htmlcommon-filter.component.ts。这是一个(或多或少)基于更复杂组件的最小示例。downgradeModule出于性能原因,我将采用这种方法。

4

1 回答 1

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

于 2018-07-12T13:20:29.187 回答