Передать услугу/поставщика для конкретного дочернего компонента для использования в качестве значения для ввода
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);
}
и в дочерних компонентах вы можете получить доступ к этой службе.