Jak uniknąć efektu circular dependency?
Angular dostarcza nam prosty sposób na dynamiczne generowanie komponentów, ale czasami pojawia się problem.

Problem
Załóżmy, że mamy dwa komponenty i serwis do dynamicznego renderowanie komponentów. Serwis posiada metodę render, która akceptuje typ komponentu jako argument np. OneComponent.
OneComponent używa naszego serwisu do wyrenderowania komponentu TwoComponent, a komponent TwoComponent używa serwisu do wyrenderowania komponentu OneComponent.
Ostrzeżenie circular dependency
Dzieje się to, ponieważ OneComponent importuje TwoComponent, a TwoComponent importuje OneComponent. Chaos, prawda?
Jakiś czas temu odkryłem ciekawy sposób na rozwiązanie tego problemu. W tym celu użyjemy InjectionsTokens i dodamy je do naszego komponentu jako providers.
Stwórzmy COMPONENT_ONE_TOKEN (COMPONENT_TWO_TOKEN token jest stworzony podobnie).
import { InjectionToken } from '@angular/core';
export const COMPONENT_ONE_TOKEN = new InjectionToken<any>('ComponentOneToken');
Dodajmy tokeny w module
@NgModule({
imports: [
CommonModule,
],
declarations: [
OneComponent,
TwoComponent
],
entryComponents: [
OneComponent,
TwoComponent
],
providers: [
RenderService,
{ provide: COMPONENT_ONE_TOKEN, useValue: OneComponent },
{ provide: COMPONENT_TWO_TOKEN, useValue: TwoComponent }
]
})
export class SomeModule {
}
Pozwala nam to na wstrzyknięcie klas komponentów
@Component({
selector: 'app-one',
templateUrl: './one.component.html',
styleUrls: ['./one.component.scss']
})
export class OneComponent {
constructor(@Inject(COMPONENT_TWO_TOKEN) private componentTwo) {
}
}
Zmieni to sposób używamy metody render w serwisie z service.render(TwoComponent) na service.render(this.componentTwo).
Podsumowanie
Rozwiązanie jest dość skomplikowane. Innym sposobem jest na pewno lepsza architektura komponentów, która nie doprowadzi do ostrzeżeń o circular dependency. Czasami się nie da.