bradrice
bradrice

Reputation: 1755

pass data from child to parent inside of router-outlet

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

Answers (2)

Md Rafee
Md Rafee

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

Saif Jerbi
Saif Jerbi

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

Related Questions