Reputation: 2382
i have a parent componet(profile-characteristics.component.ts) and a child modal component(pc-predefined-list.component.ts).
When a drop down option is changed in the parent component template, i need to show its corresponding values in the child modal template.
The child component method is as follows.
constructor(
private utilsService: UtilsService,
private route: ActivatedRoute,
private _fb: FormBuilder,
@Inject(DOCUMENT) private document: Document
) {}
ngOnInit() {
this.pListValueForm = this._fb.group({
pListValues: this._fb.array([this.initItemRows()]) // here
});
//this.setListValues();
this.route.params.subscribe(params => {
this.accountId = params['id'];
});
}
setListValues() {
this.pListValueForm = this._fb.group({
pListValues: this._fb.array([]) // here
});
const control = <FormArray>this.pListValueForm.controls['pListValues'];
this.selectedListValues.forEach(x => {
control.push(this.patchValue(x.profile_characteristic_list_value_id, x.name, x.sort_order))
});
}
parent component
ngAfterViewInit() {
// child is set
this.child.setListValues();
}
The modal will work correctly if i hard code this.selectedListValues as follows.
this.selectedListValues = [ { "profile_characteristic_list_value_id": "13110afd-f459-11e7-9d12-408d5cbccb60", "profile_characteristic_list_id": "1", "name": "value 2", "sort_order": "2" }, { "profile_characteristic_list_value_id": "13110e5f-f459-11e7-9d12-408d5cbccb60", "name": "value 4", "sort_order": "4", "profile_characteristic_list_id": "2", } ];
I need to pass the "selectedListValues" dynamically from parent component to the child component. Any ideas on how to achieve this?
Upvotes: 0
Views: 1527
Reputation: 1538
I have used this pattern many times and it works great!
Two component (a parent component and its children or other different component) can share a service whose interface enables bi-directional communication.
Like in the Observer pattern, in this case the scope of the service instance is the notification from a component (Publisher) and other componentents (Subscriber).
To pass to the child the complex data type (like your "selectedListValues") I usually use an external class which represents with its fields tha data:
model.ts
export class ListValues
{
public profile_characteristic_list_value_id: string;
public profile_characteristic_list_id: number;
public name: string;
public sort_order: string;
}
mycomponent.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { ListValues} from './model';
@Injectable()
export class MyComponentService{
// Observable
private sampleObservable = new Subject<ListValues>();
// Observable boolean streams
sampleSubscriber = this.sampleObservable.asObservable();
// Event for notification from publisher to subscriber
sampleEventChanged(value:ListValues)
{
this.sampleObservable.next();
}
}
In the component who wants to notify all subscribers a change of its state:
mycomponent-publisher.ts (for you is the parent component)
import { Component } from '@angular/core';
import { MyService } from './mycomponent.service';
@Component({
selector: 'app-my-control-publisher',
template: `
<h2>This is the publisher control</h2>
<button (click)="announce()">Announce to subscriber</button>
`,
providers: [MyService]
})
export class MyControlPublisherComponent
{
constructor(private myService: MyService) { }
announce()
{
listValues = new ListValues();
// here set the info to notify...
this.myService.sampleEventChanged(listValues);
}
}
In the subscriber component who want to get the notification.
mycomponent-subscriber.ts (for you is the child component)
import { Component, OnDestroy } from '@angular/core';
import { MyService } from './mycomponent.service';
import { Subscription } from 'rxjs/Subscription';
import { ListValues} from './model';
@Component({
selector: 'app-my-control-subscriber',
template: `
<h2>This is the subscriber control</h2>
`,
})
export class MyControlSubscriberComponent
{
// Subscriptions
private componentSubscription: Subscription;
constructor(private myService: MyService)
{
// Subscription of the notifications
this.componentSubscription= this.myService.sampleSubscriber.subscribe(value =>
{
// Put the code for manage the notification here
// value is of type 'ListValues'
}
}
ngOnDestroy()
{
// Release subscription to avoid memory leaks when the component is destroyed
this.componentSubscription.unsubscribe();
}
}
Upvotes: 0
Reputation: 109
You have two options that come to mind:
1) Make the child component a Viewchild of the parent, allowing you to to call the child elements function from the parent component and passing the selectedListValues as a parameter. How you trigger the function call is up to you.
2) Use data binding. Define an Output in the parent component from your list selection, emitting the list. Then implement an Input in the child component to bin a list as a property. Passing that list every time the selection from your parent component is updated, could trigger a function displaying the list for example. See here Let me know if you need more help or code examples, but i am a fan of learning by doing in terms of longterm imporvement.
Have fun coding
Upvotes: 0
Reputation:
If it were my issue, I would create an Input into your child component :
@Input() chosenValue: any;
Then passe a value to the child :
<app-pc-predefined-list [chosenValue]="YourParentVariable"></app-pc-predefined-list>
The, I would make my child implement onChanges
:
export class PcPredefinedListComponent implements OnChanges {
// Your code ...
ngOnChanges(changes: SimpleChanges) {
console.info(changes);
}
}
This way, everytime your parent's list is changed, your child will be notified and will be able to launch your method to filter the choices of your list.
Upvotes: 1