3

I have a page component with a button that opens a PopoverController. According to the Ionic Docs, popovers need another specific component for its content.

In the main page I have a function that I need to call from the popover component, but I haven't found how to access to the "parents'" methods. I've tried with @ViewChild but the child is undefined.

import { Component, ViewChild } from '@angular/core';
import { Content, NavController, NavParams, Platform, PopoverController, ViewController } from 'ionic-angular';

// Parent page:
@Component({
    selector: 'page-favorites',
    templateUrl: 'favorites.html'
})
export class FavoritesPage {
    constructor(public popoverCtrl: PopoverController) {
    }

    openOptions(ev?: Event) {
        let popover = this.popoverCtrl.create(FavoritesPopover);
        popover.present({ ev: ev });
    }

    showConfirm() {
        // This is the function I need to call from FavoritesPopover
    }
}

// Popover content:
@Component({
  template: `
    <ion-list>
        <button ion-item (click)="showConfirm()">Show confirm</button>
    </ion-list>`
})
export class FavoritesPopover {
    @ViewChild(FavoritesPage) favoritesPage: FavoritesPage;

    showConfirm() {
        this.favoritesPage.showConfirm(); // It doesn't work, favoritesPage is undefined
    }
}

As you can see, I'm just starting to work with Ionic 2 and Angular, so any help would be so thankful!

Sébastien
  • 11,860
  • 11
  • 58
  • 78
Àlex P
  • 33
  • 1
  • 3

3 Answers3

12

You can pass data (and functions) to the popover by passing an object as the second argument to the create method:

openOptions(ev?: Event) {
    let popover = this.popoverCtrl.create(FavoritesPopover, {
        showConfirm: function() {
            alert('yay');
        }
    });
    popover.present({ ev: ev });
}

Then, you should inject NavParams to your popover view, and get the function you passed:

import {NavParams} from 'ionic-angular';

export class FavoritesPopover {
    constructor(public params: NavParams) {}

    showConfirm() {
        this.params.get('showConfirm')(); 
    }
}
Schlaus
  • 18,144
  • 10
  • 36
  • 64
  • Thank you @Schaus ! I've used the arguments of popover's create method to pass not only the function but also reference to all objects it uses and now it works well. – Àlex P Jan 31 '17 at 11:35
  • Ok, the example with `alert('yay');` works. But if I try to use an existing fuction of the class, I get undefined! Why can I not call outside functions? E.g.: `this.someFunction()` – alex351 Oct 11 '17 at 12:10
  • The way I see it is, you do not use an existing function of the class, but are creating a new one, inside `this.popoverCtr.create...`. Am I correct? – alex351 Oct 11 '17 at 12:32
  • This worked for me! Your `function` can also receive back a parameter if you need, for example `function(param1) { alert(param1); }` and `this.params.get('showConfirm')('High five!');` – Dale Zak Oct 13 '17 at 19:18
  • I am looking this solution for ionic4, kindly share your suggestion. Thanks. – Kamlesh Apr 03 '19 at 08:09
2

For the people who are struggling with same issue, the simplest way is to pass the reference of the page as follows:

let popover = this.popCtrl.create(PopoverPage, { homeRef: this });
popover.present({
  ev: myEvent
});

and the in popover page you can get the reference and access all variables and functions of that page like below:

homePage: any;

changePassword() {
    this.homePage = this.navParams.get('homeRef');
    this.homePage.changePassword();
    this.viewCtrl.dismiss();
}
VaibS
  • 1,627
  • 1
  • 15
  • 21
0

Parent page:

      public list() {
        this.popover.dismiss();
      }

      public async more(ev:any) {
        this.popover = await this.pop.create({
          component: PopoverPage,
          componentProps: {ref: this},
        });

        return await this.popover.present();

      }

Popover page:

  export class PopoverPage {

    parentPage: any;
    constructor(
        public params: NavParams
    ) { 
    }

    order() {
        this.parentPage = this.params.get('ref');
        this.parentPage.list();
    }

}