Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ionic 3: Modal Controller - Get component Instance

I am showing a Component EventFeedbackComponent via ModalController. Now I want to subscribe to a Subject in EventFeedbackComponent. How do I get access to the component instance, to achieve my goal.

My current code:

let modal   =   this.modalCtrl.create(EventFeedbackComponent);
modal.present();

// This is not working. Throws the error "ERROR TypeError: Cannot read property 'subscribe' of undefined"
modal._component.feedbackSubmit.subscribe(feedbackResponse => {
    console.log(feedbackResponse);
});

Documentation didn't help in this regard: https://ionicframework.com/docs/api/components/modal/ModalController/

My use case:

  • I have a list of Events in my Service, for which I need to get Feedback.
  • EventFeedbackComponent has controls to get Feedback for a Single Event.
  • Now, I show the EventFeedbackComponent to get feedback for First Event and listen for the event feedbackSubmit via Subject
  • On submission of feedback, I show a Success Toast and switch my service variable in Service to show next event.
  • Above point is repeated, till I get feedback for all Unreviewed events with the same Component shown via Model.
like image 909
saiy2k Avatar asked Sep 18 '17 05:09

saiy2k


1 Answers

Option 1 Dismiss with params

Ionic modal component gives us the opportunity to close dialog with some arguments:

modal.ts

constructor(public viewCtrl: ViewController) {
  this.prop = params.get('prop');
}

dismiss() {
  this.viewCtrl.dismiss({ test: '1' });
}

and in opener we should have:

opener.ts

let modal = this.modalCtrl.create(TestComponent, { 'prop': 'prop1' });

modal.onDidDismiss(data => {
  alert('Closed with data:' + JSON.stringify(data));
});

If it is not enough for you then

Option 2 Communication through ViewContainer.emit

you can use ViewController::emit method to send data to opener

modal.ts

constructor(public viewCtrl: ViewController) {}

sendFeedBack() {
  this.viewCtrl.emit({ someData: '2' });
}

opener.ts

let modal = this.modalCtrl.create(TestComponent, { 'prop': 'prop1' });

modal.onDidDismiss(data => {
  alert('Closed with data:' + JSON.stringify(data));
});

modal.present().then(result => {
  modal.overlay['subscribe']((z) => {
    alert(JSON.stringify(z));
  })
});

Option 3 Input callback

Since we can pass any parameter to modal then let's pass callback function:

opener.ts

let modal = this.modalCtrl.create(TestComponent, { 
  'prop': 'prop1', 
  onFeedBack: (data) => {
    alert('Input callback' + JSON.stringify(data));
  }
});

modal.ts

onFeedBack: Function;

constructor(params: NavParams) {
  this.onFeedBack = params.get('onFeedBack');
}

sentThroughInputCallback() {
  this.onFeedBack({ s: '2' });
}

If you still want to get component instance then:

Option 4 Get component instance

You can get component instance only after it has been created:

opener.ts

let modal = this.modalCtrl.create(TestComponent, { 'prop': 'prop1' });

modal.present().then(result => {
  const testComp = modal.overlay['instance'] as TestComponent;
  testComp.feedbackSubmit.subscribe(() => {
    alert(1);
  })
});

Check it out on Ng-run Example

like image 125
yurzui Avatar answered Sep 27 '22 17:09

yurzui