Reputation: 3267
I have a parent component with two children.
The parent component has a property which is actually a dictonary like this:
dict = {a: 0, b: 0, c: 0};
I do input binding so that both of the child components can have access to dict
.
<app-child-a [dict]="dict"></app-child-a>
<app-child-b [dict]="dict"></app-child-b>
Child A changes a property of dict
@Input() dict: any;
someFunctionInChildA() {
this.dict.b = 1;
}
I can verify that the Parent component knows about this change.
ngAfterInit() {
setInterval(() => console.log(this.dict), 1000);
}
This prints 0
s until someFunctionInChildA
is triggered after which it prints 1
s.
Here's my problem: child B doesn't seem to see the change. Here's some code from child B
@Input() dict: any;
ngAfterInit() {
setInterval(() => console.log(this.dict), 1000);
}
This prints 0
s all the time, even after someFunctionInChildA
has been triggered.
Do I not understand how property binding works? Or is it more likely that I have a silly or unrelated bug elsewhere?
Upvotes: 0
Views: 833
Reputation: 3267
I've figured this one out, and I doubt anyone else will find this useful as it's a rare thing to happen...
A couple of days ago I actually made a service which would save and update dict
into Firebase, and this would sync up with my components via rxjs. But I left some of the old logic behind (that is, the logic whereby dict
was being managed by the component rather than the service).
I will mark this as the correct answer, but the real credit goes to @bryan06 for his good explanation of the correct pattern for this sort of application.
Upvotes: 0
Reputation: 29345
as you can see here: https://stackblitz.com/edit/angular-7-master-nxys2f?file=src/app/hello.component.ts
the code in question works fine. BUT.. this is a very bad practice. as this sort of at a distance mutation creates hard to reason about code and hard to understand bugs. I'm guessing your real application is a bit more complex, and you're probably accidentally breaking the reference somewhere. This is why you should use a shared service model and rxjs to share information between components:
@Injectable()
export class DictService {
private dictSource = new BehaviorSubject({a: 0, b: 0, c: 0})
dict$ = this.dictSource.asObservable()
setDict(dict) {
this.dictSource.next(dict)
}
}
then inject into your components and subscribe:
constructor(private dictService: DictService) {
this.dictSub = this.dictService.dict$.subscribe(dict => this.dict = dict) // don't forget to unsubscribe!
}
and use the service to update:
someFunctionInChildA() {
this.dict.b = 1;
this.dictService.setDict(this.dict)
}
Upvotes: 2