【问题标题】:Angular 7: injection with dependencies for ngComponentOutletAngular 7:为 ngComponentOutlet 注入依赖项
【发布时间】:2020-03-14 19:36:39
【问题描述】:

我需要为我的ngComponentOutlet 使用某种@Input() 装饰器。

但是 Angular 似乎没有这个功能。相反,我想在我的出口组件中传递的所有东西都应该通过Injector 提供。

如果我想在可注入类中启动我想要提供的东西,那很好。但我需要更深入地研究并在创建 Injector 步骤时提供某种可观察变量(例如Observeble<number> 类型)。但我无法在出口组件内获得可观察的变量。出现以下错误:NullInjectorError: No provider for [object Object]!

这是一个代码示例,我从 Angular 文档 (angular.io/api/common/NgComponentOutlet) 中得到了这个模式并稍作修改:

@Injectable()
export class Greeter {
    suffix$: Observable<number> = null;
    constructor(private _suffix$: Observable<number>) {
        this.suffix$ = this._suffix$;
    }
}

@Component({
    selector: 'complete-component',
    template: `Complete: {{ greeter.suffix$ | async }}`
})
export class CompleteComponent {
    constructor(public greeter: Greeter) {
        this.greeter.suffix$.subscribe(data => console.log('data', data));
        // not working
    }
}

@Component({
    selector: 'ng-component-outlet-complete-example',
    template: `
        <ng-container *ngComponentOutlet="CompleteComponent; 
                                        injector: myInjector;"
    })
export class NgTemplateOutletCompleteExample {
    CompleteComponent = CompleteComponent;
    myInjector: Injector;

    suffix$: Observable<number> = of(3);

    constructor(injector: Injector) {
        this.myInjector =
            Injector.create({providers: [{provide: Greeter, deps: [this.suffix$]}], parent: injector});
    }
}

那么我怎样才能在出口组件中获取和订阅这个$suffix 变量。

P.S. 如果我将NgTemplateOutletCompleteExample 提供到deps 数组中并在可注入组件Greeter 中获取NgTemplateOutletCompleteExample.suffix$ - 它会起作用。但问题是我有很多 NgTemplateOutletCompleteExample 组件,这对我来说是无效的。

【问题讨论】:

    标签: angular typescript dependency-injection ng-component-outlet


    【解决方案1】:

    对于采用输入并返回输出的组件的动态注入,我遇到了类似的问题。 Angular 原生不支持动态组件上的@Input()@Output

    你可以使用包 NgDynamicComponent:https://www.npmjs.com/package/ng-dynamic-component

    NgComponentOutlet 语法支持

    这个包支持 NgComponentOutlet 语法,你可以在这里看到: https://www.npmjs.com/package/ng-dynamic-component#ngcomponentoutlet-support

    根据我从您的代码中看到的,这就是您所要求的:NgComponentOutlet + Inputs 支持。

    为更高级的东西定制动态注入器

    您还可以创建自定义注入器:https://www.npmjs.com/package/ng-dynamic-component#extra

    【讨论】:

      【解决方案2】:

      最主要的是 Injector - 是一个静态注入器。因此,要在组件 oultet 中提供任何数据(或获取任何回调),我必须使用 useValue 而不是 deps

      NgTemplateOutletCompleteExample 中的构造函数应该是这样的:

      constructor(injector: Injector) {
          this.myInjector =
              Injector.create({providers: [{provide: Greeter, deps: [], useValue: {suffix$: this.suffix$}], parent: injector});
      }
      

      【讨论】:

      • 我不确定你的更新。 NgDynamicComponent 没有解决你的问题?
      【解决方案3】:

      为了了解您收到该错误的原因,我建议您查看文档中的 Dependency Providers

      错误来自这里

      Injector.create({providers: [{provide: Greeter, deps: [this.suffix$]}], parent: injector});
      

      简单地说,deps 数组必须是有效 DI 令牌的列表,并且没有为 this.suffix$ 配置令牌。

      引自来源(Angular 8.0.0)

      export interface FactorySansProvider {
        /**
         * A function to invoke to create a value for this `token`. The function is invoked with
         * resolved values of `token`s in the `deps` field.
         */
        useFactory: Function;
      
        /**
         * A list of `token`s which need to be resolved by the injector. The list of values is then
         * used as arguments to the `useFactory` function.
         */
        deps?: any[];
      }
      

      这是解决它的一种方法:

      const OBS_TOKEN = new InjectionToken('obs');
      
      @Injectable()
      export class Greeter {
        greeterProp = 'hello!';
      
         constructor (@Inject(OBS_TOKEN) public suffix$: Observable<any>) {
          console.log('[GREETER]', this.suffix$)
        }
      }
      
      @Component({ /* ... */ })
      export class NgTemplateOutletCompleteExample {
       /* ... */
      
       myInjector = Injector.create({
          providers: [
            { provide: Greeter, deps: [OBS_TOKEN], },
            { provide: OBS_TOKEN, useValue: this.dummyObs$ },
          ],
          parent: this.inj,
        })
      
       /* ... */
      }
      

      StackBlitz

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-15
        • 2016-02-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-01
        • 2017-01-15
        相关资源
        最近更新 更多