Reputation: 1755
I have a parent component with a router-outlet. I want to call the parent function with a child event. I understand @Input() and @Output, but how do you use them with router-outlet
<router-outlet (tapVocab)="openVocabModal($event)"></router-outlet>
Doesn't seem to work for me. In my child I have:
@Output() tapVocab = new EventEmitter<string>();
callParent(val) {
console.log('calling parent', val);
this.tapVocab.next(val);
}
Upvotes: 12
Views: 20859
Reputation: 5530
From angular
<router-outlet>
Acts as a placeholder that Angular dynamically fills based on the current router state.
<router-outlet>
does not offer a means to bind data to loaded components or emit events from them to parents.
But it has two events:
activate — emits any time a new component is instantiated.
deactivate — emits when the component is destroyed.
<router-outlet (activate)="componentAdded($event)" (deactivate)="componentRemoved($event)"></router-outlet>
But I don't think it will be useful for your case.
But you can communicate like any other communication between two unrelated components using service.
common.service.ts:
@Injectable()
export class CommonService {
private data = new BehaviorSubject('default data');
data$ = this.data.asObservable();
changeData(data: string) {
this.data.next(data)
}
}
app.component.ts:
@Component({
selector: 'app-component',
template: `<p>{{data}}</p>`
})
export class AppComponent implements OnInit {
data: string;
constructor(private service: CommonService) { }
ngOnInit() {
this.service.data$.subscribe(res => this.data = res) //read the invoked data or default data
}
}
child.component.ts:
@Component({
selector: 'app-component-two',
template: `
<p>{{data}}</p>
<button (click)="newData()">Next Data</button>`
})
export class ComponentTwoComponent implements OnInit {
data: string;
constructor(private service: CommonService) { }
ngOnInit() {
this.service.data$.subscribe(res => this.data = res)
}
newData() {
this.service.changeData('Changed Data'); //invoke new Data
}
}
Upvotes: 26
Reputation: 675
Components loaded using router-outlet couldn't be handled as ones injected in the template using input/output mechanism.
You need to implement a shared service, this service should provide a Stream of communication between Parent and Child.
example:
@Injectable()
export class MyService{
private data$: Subject<any> = new Subject<any>();
next(data:any):void {
this.data$.next(data);
}
select(): Observable<any> {
this.data$.asObservable();
}
}
you need know to inject this service into your components and watch/push data throw it
Upvotes: 0