Передать услугу/поставщика для конкретного дочернего компонента для использования в качестве значения для ввода

FormService содержит состояние частей формы.

      export class ArrayComponent implements OnInit {

   formServices: FormService[] = [];

   constructor(
        @Inject(FormService) public parentFormService: FormService,
    ) {
    }

   ngOnInit(): void {
      // Here I create lets say 10 FormService objects, that have to go to there separated child components.
      this.parentFormService.data$.subscribe((d: any[]) => d.foreach((v: any) => this.formServices.push(new FormService(v))))
   }
}

Давайте представим, что на основе каких-то данных я создаю новый FormService. Мне нужно иметь возможность передать этот созданный FormService для определенного дочернего компонента.

      <ng-container *ngFor="let s of formServices">
   <array-item [inject/providers]="s"></array-item>
</ng-container>

Есть ли способ передать этот инъекционный сервис в компонент как инъекционный?

Вы можете спросить, зачем мне нужно, чтобы он был инъекционным или почему я не могу просто передать его как @Input. Проблема в том, что внизу в дереве компонентов есть, например,TextInputComponentкоторый пытается внедрить FormService для сохранения состояния и выполнения других операций ввода.

Я очень хочу сделать то, что@Component({providers: []})делает, но вне компонента, поэтому я могу напрямую управлять предоставленной службой и иметь доступ к ней из родительского и дочернего компонентов.

РЕДАКТИРОВАТЬ: // Более точная вещь, которую я хочу сделать упрощенной

      <array-item [inject/providers]="formServices[0]"></array-item>
<array-item [inject/providers]="formServices[1]"></array-item>
<array-item [inject/providers]="formServices[2]"></array-item>
<array-item [inject/providers]="formServices[3]"></array-item>

а затем внутри компонента элемента массива есть компонент, который использует @Inject для внедрения FormService и его использования.

2 ответа

Это очень возможно.

Для каждого ребенка можно создатьInjectorтак -

      ...

constructor(
        ...
        private injector: Injector,
        ...
    ) {
    }
...

Injector.create({providers: [...providder here...], parent: this.injector})

А затем передайте его компоненту, который отображает следующие дочерние элементы следующим образом:

      ...
@Input() injector!: Injector;
...
    constructor(
        ...
        public viewContainerRef: ViewContainerRef,
        ...
    ) {

    }
...
ngOnInit(): void {
        ...
        const component = this.viewContainerRef.createComponent(...Component..., {
            ...
            injector: this.injector
            ...
            }),
        });
        ... // Set @Input attributes here with component.instance.
        component.changeDetectorRef.detectChanges();
        ...
    }

На самом деле все дети могут получить доступ к родительским провайдерам, так просто:

      @Component({providers: [FormService]})

в родительском компоненте делает все, что вы хотите.

Для экземпляров службы различий вы можете спроектировать это следующим образом:

Добавить вход для компонентаarray-item [service-config]="...". В компоненте:

      @Inject(FormService) public parentFormService: FormService
ngOnInit() {
     this.parentFormService.reConfigure(this.serviceConfig);
}

и в дочерних компонентах вы можете получить доступ к этой службе.

Другие вопросы по тегам