Reputation: 62704
I have a parent AppComponent and another component called "ChildComponent". Both of them share a service called "appState" that is injected into both (I am using https://github.com/AngularClass/angular-starter, the app.service.ts class is here https://github.com/AngularClass/angular-starter/blob/master/src/app/app.service.ts which is the appState I am referring to).
ChildComponent has its own property "mylist" that is an array of objects, set equal to this.appState.mylist.
@Component(...)
export class ChildComponent {
mylist = any;
constructor(@Inject(AppState) appState) {
public appState = appState;
mylist = appState.state.mylist;
}
}
I have a template for ChildComponent that shows {{mylist}}
ParentComponent has a template that has a single "Add Me" button whose sole function is to add to this.appState.mylist.
My problem is, when I click on the "Add Me" button on the parent component, and within the function I log this.appState.mylist.
@Component(...)
export class AppComponent {
constructor() {
public appState = appState;
appState.mylist = [];
}
addMe() {
this.appState.state.mylist.push({"itemName":"Something"});
console.log(this.appState.mylist) // this outputs correctly and I see mylist growing
}
}
I read about how eventEmitters can emit events to update the parent, but in my case, I want to update a component that is within the AppComponent template. What is wrong? How can I make it so that "mylist" in my child.component.html will show the right data?
All of the documentation I've seen appears to talk about EventEmitters which communicate from child to parent, which does not appear to work for me since I am trying to communicate from my parent AppComponent to child ChildComponent.
Issue plunkr: https://plnkr.co/edit/xaE905r4xNZcVJzWQwsr?p=preview
Upvotes: 3
Views: 2544
Reputation: 13307
UPDATE:
The way OP has his service setup, the problem is child component wasn't getting the updated appState.mylist
. So, the solution I am offering is to use Subject
and Observable
to notify the child component of changes and pull in new data via subscription.
child.components.ts:
mylist: any;
constructor(private appState: AppState){
this.appState.dataString$.subscribe(
data => {
this.mylist = data.mylist;
});
}
Please see the plunker demo for service.ts
code.
Original Post:
Since you have parent-child relation you can pass mylist
to child component as easily as just using data binding.
<child-component [mylist]="mylist"></child-component>
In child component, you can use @Input()
to bind the passed data from parent to mylist
variable in child component.
If you still want to use shared service, then you are on right track, just need to clean up the code in parent and child components, which can look like following:
parent:
constructor(private appState: AppState){
this.appState.mylist = [];
}
addMe() {
this.appState.mylist.push({"itemName":"Something"});
console.log(this.appState.mylist) // this outputs correctly and I see mylist growing
this.mylistFromParent.push({"itemName":"Something"});
}
child:
mylist: any;
constructor(private appState: AppState){
this.mylist = this.appState.mylist;
}
I have created this demo illustrating both cases.
Hope this helps!
Upvotes: 5