Angular does have Dependency Injection framework that provides different approaches to handle a situation where something like React Context API is needed.
In the "The Problem" section, you saw that to pass down a value to the descendants' components you have to declare an @Input at every component even though that a component might merely act as a wrapper for another component. This actually can be changed by providing an InjectionToken to the ancestor component and inject that token at any descendant component to utilize the value.
Change the root component to include the InjectionToken
const FamilyNameToken = new InjectionToken('FamilyName');
@Component({
selector: 'app-root',
template: `<app-grandchild> </app-grandchild>`,
providers: [{provide: FamilyNameToken, useValue: 'The Angulars'}]
})
export class AppComponent { }
And for the component that needs the value to inject the InjectionToken
@Component({
selector: 'app-grandchild',
template: `Family Name: {{familyNameValue}}`
})
export class GrandchildComponent {
constructor(@Inject(FamilyNameToken) public familyNameValue: string) { }
}
That might look easy and simple at first, but the catch is when you want to update the value you need to have a kind of RxJSSubject because Angular will hard inject the value that corresponds to the InjectionToken into the GrandchildComponent. The other way is to use a class provider to act as a state holder.
class FamilyName {
private state = new ReplaySubject(1);
public setName(value: string) {
this.state.next(value);
}
public getName() {
return this.state.asObservable();
}
}
The root component will inject the class and sets the value.
Angular does have Dependency Injection framework that provides different approaches to handle a situation where something like React Context API is needed.
In the "The Problem" section, you saw that to pass down a value to the descendants' components you have to declare an
@Input
at every component even though that a component might merely act as a wrapper for another component. This actually can be changed by providing anInjectionToken
to the ancestor component and inject that token at any descendant component to utilize the value.Change the root component to include the InjectionToken
And for the component that needs the value to inject the InjectionToken
That might look easy and simple at first, but the catch is when you want to update the value you need to have a kind of RxJS
Subject
because Angular will hard inject the value that corresponds to theInjectionToken
into theGrandchildComponent
. The other way is to use a class provider to act as a state holder.The root component will inject the class and sets the value.
And for the component that needs the value to inject the
FamilyName
class and subscribe to the changes.Also, you can re-provide the
FamilyName
class at any component level so it can act as theProviderComponent
.With that said, having a way to pass down a value within the component template it self can reduce the amount of class you will need.