简体   繁体   English

有没有办法如何从所有多个级别使用Angular多提供程序?

[英]Is there a way how to use Angular multi providers from all multiple levels?

I am wondering whether it is possible to get the angular multi-providers from (ideally) all ancestors. 我想知道是否有可能从(理想情况下)所有祖先获得角度多供应商。

Lets say that I have a INJECTION_TOKEN X and I have a component structure like this: 让我们说我有一个INJECTION_TOKEN X ,我有一个像这样的组件结构:

<comp-a>
    <comp-b>
       <comp-c></comp-c>
    <comp-b>
<comp-a>

comp-a providers: providers: {provide: X, useValue: "A", multi: true} comp-a providers: providers: {provide: X, useValue: "A", multi: true}

comp-b providers: providers: {provide: X, useValue: "B", multi: true} comp-b提供者: providers: {provide: X, useValue: "B", multi: true}

Is there a way how to get ["A", "B"] in comp-c when I use Dependency injection like: 当我使用依赖注入时["A", "B"]有没有办法在comp-c获得["A", "B"] ,如:

constructor(@Inject(X) obtainedArray:TypeOfX[]) {
    console.log(obtainedArray.length); //Expected to be 2
}

I have tried to use this provider in comp-b but it is throwing a cyclic DI expection: 我试图在comp-b使用这个提供程序,但它正在抛出循环DI期望:

providers:[
    {provide: X, useExisting: X, multi: true}
    {provide: X, useValue: "B", multi: true}
]

As the following article states: 如下文所述:

Angular stores providers on element by using prototypical inheritance . Angular通过使用原型继承来存储元素的提供者。 So, never mind whether you use multi or not you will get the following object that contains all providers on current element: 所以,不管你是否使用multi ,你将获得包含当前元素上所有提供者的以下对象:

在此输入图像描述

As you can see all providers are here, but since angular just uses square brackets to get provider from element you will get only nearest provider. 正如您所看到的那样,所有提供商都在这里,但由于angular只使用方括号从元素中获取提供者,因此您只能获得最近的提供者。

To workaround this you can use addition token that uses factory to collect all parent providers: 要解决此问题,您可以使用使用工厂的附加令牌来收集所有父提供者:

import { Component, VERSION, InjectionToken, 
  Inject, SkipSelf, Optional } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <comp-a>
        <comp-b>
            <comp-c></comp-c>
        </comp-b>
    </comp-a>
  `
})
export class AppComponent { }

const X = new InjectionToken('X');

const XArray = new InjectionToken('XArray');

const XArrayProvider = {
  provide: XArray,
  useFactory: XFactory,
  deps: [X, [new SkipSelf(), new Optional(), XArray]]
};

export function XFactory(x: any, arr: any[]) {
  return arr ? [x, ...arr] : [x];
}

@Component({
  selector: 'comp-a',
  template: `<ng-content></ng-content>`,
  providers: [
    { provide: X, useValue: "A" },
    XArrayProvider
  ]
})
export class CompA { }


@Component({
  selector: 'comp-b',
  template: `<ng-content></ng-content>`,
  providers: [
    { provide: X, useValue: "B" },
    XArrayProvider
  ]
})
export class CompB { }


@Component({
  selector: 'comp-c',
  template: `{{ tokens }}`
})
export class CompC {
  constructor( @Inject(XArray) public tokens: any[]) { }
}

Ng-run Example Ng-run示例

No, you can't do what you are trying to do with dependency injection, as far as I know. 不,据我所知,你不能做依赖注入你想做的事情。 When you provide something in a component, it automatically hides previous providers with the same token. 当您在组件中提供某些内容时,它会自动使用相同的令牌隐藏以前的提供程序。 This is the way it is intended to work. 这是它的工作方式。

To achieve what you need, the only solution I can think of is to pass the providers as inputs . 为了实现您的需求,我能想到的唯一解决方案是将提供者作为inputs

I mean, comp-a declares a provider. 我的意思是, comp-a声明了一个提供者。 comp-b also does it, but accepts an input containing a provider or array of providers. comp-b也可以,但接受包含提供者或提供者数组的input Then comp-b can add its own provider to the array and pass it as an input to comp-c . 然后comp-b可以将自己的提供者添加到数组中,并将其作为输入传递给comp-c

I do not understand why exactly you want this, though ... 我不明白为什么你想要这个,不过......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM