How to catch EventEmitter from PopOver as a separate component?

In a page I have a competent(child) to handle a PopOver menu that make changes to some variables on the page(parent).

The PopOver is written as a separate component so I can reuse it.
In the Component I hv:
import { Component, Output, EventEmitter } from '@angular/core';

@Component({
    template: `
        <ion-list radio-group [(ngModel)]="someVar"  (ionChange)="changeSomthing()">
          <ion-item>
            <ion-label>A</ion-label>
            <ion-radio value="A"></ion-radio>
          </ion-item>
          <ion-item>
            <ion-label>B</ion-label>
            <ion-radio value="B"></ion-radio>
          </ion-item>
          <ion-item>
            <ion-label>C</ion-label>
            <ion-radio value="C"></ion-radio>
          </ion-item>
        </ion-list>
    `
})

export class Popover {
    constructor(private navParams: NavParams) {};
    someVar: string;
    @Output('update') update : EventEmitter<string> = new EventEmitter<string>();

    changeSomthing(){
        if (this.someVar) {
            this.globalVar.someVar= this.someVar;
            this.update.emit( this.someVar );
        }
    }
}

@Component({
  selector: 'someButton',
  templateUrl: 'menu.html'
})
export class Menu{
    constructor(private popoverCtrl: PopoverController, public globalVar: GlobalVar) {}
    presentPopover(ev) {
        let popover = this.popoverCtrl.create(PopoverLang, {});
        popover.present({
          ev: ev
        });
    }
}

Then I tried to catch the changes in the page:

    <ion-buttons>
            <someButton (update)="someUpdate($event)"></someButton>
    </ion-buttons>
    <p>
        {{someVar}}
    </p>

in the page.ts:

export class HomePage {

    constructor(public navCtrl: NavController) {}
    someVar: string;
    ngOnInit() { 
        this.someVar= "A";
    }
    someUpdate(event) {
        this.someVar= event;
        console.log("catch");
    }
}

Though it seems someUpdate(event) was never fired up, what did I missed?
I followed a tutorial similar here:

First step to debug your code is to type variables, so your runtime bad behavior becomes compile time errors. You will help yourself a lot if you never use the word any in your code again.

OK, i tried using String instead of Any and the result is the same…

…but you aren’t emitting a string…

okay…

I edited some code to simplify it from the project i am working on so perhaps i missed that, I tried object, string, and any.

but then it’s still not working.
It seems its not triggering the someUpdate(event), I was thinking a popover component cannot emit changes to a parent page.

I haven’t read the tutorial you posted, but I find your code confusing. If you’re using Ionic’s PopoverController, I don’t understand why it’s better to use EventEmitter than to use the dismiss method of ViewController. The docs recommend ViewController.dismiss(). EventEmitter might work anyway, especially if you want the popover to remain visible while you make changes in real time base on user input. So I don’t know what you’re trying to do, and I don’t know how your project code (which is different from the code you posted) is behaving. It isn’t easy to help you.

1 Like

I can use dismiss to get it work alright.

Yes in this case I want to keep the popover visible while changes were made. The problem so far I find is that EvenEmitter did not trigger someUpdate(event) .

The project code is different in terms of the names of the variables and functions.

But you’re emitting a string and receiving an event. Of course you’re going to have problems. Have you tried any console.log statements to see exactly what is being submitted and received?

That’s how the tutorial did it… and some other tutorials i found also did in similar ways, if you saw some other tuorials or docments online that were done differently ok please let me know, I might be reading up the wrong things… :neutral_face:

I tried sth similar with other component(that doesn’t run in a popover) and the same code would work.

Furthermore, If what is transmitted were wrong in format, as you suggested, at least the function someUpdate($event) would respond and will show an error saying the wrong type of object is received. However in this case the function just dun run at all.

So… yea I am a bit confused here, if this just wont work with a popOver and the communication should only be conducted with onDismiss :disappointed_relieved:

You might want to stop trusting what you see online.

(You could buy and read a book: The FullstackIO book on Angular is superb.)

Such a friendly forum.

I came here looking for answers.

With some code showing what i did, with a link to a tutorial of how I get this far, and a question clearly stated.

Then I got a reply telling me to fxxk off and go to buy and read books :mask:

3 Likes

Hello,
I had the same problem today and found a solution.

I don’t think you can use an event emitter as described in your tutorial. But the PopoverCtrl has already an event emitter included that you can listen to.

  presentPopover(myEvent) {
    let popover = this.popoverCtrl.create(PopoverPage);
    popover.present({
      ev: myEvent
    });

    popover.onDidDismiss( (data) => {
      console.log(data);
    })
  }

then in your PopoverPage you can send data via the dismiss function

export class PopoverPage {
  constructor(private viewCtrl: ViewController) {}

  yourClickFunction(data) {
    this.viewCtrl.dismiss(data);
  }
}

The main problem with this solution is that you have to close your popover in order to receive the data. I didn’t found yet a solution where it can stay open.

The ViewCtrl in the popover has also an emit function but I don’t see yet how to listen for this in the parent component.

Hope this helps.

2 Likes

thanks for the feedback.

I am currently using onDidDismiss for that matter and it worked. I was just wondering if it is possible to keep the popoever stay open while doing so.

A quick look at the example from:

I thought it would be possible on the first glance, but then I realize it might only possible becuz in the example the popover only changes the style of element but not passing any data? Perhaps you could crack that to see if there’s another way around it. However my goal was to pass data, so it cant work the same way.

Let’s hope there’s a way to emit data without closing the popoever in future with ionic :stuck_out_tongue:

If you really need it I guess there is a workaround.

Just use a provider that is included in both your components and use a public Observable/Subscription or other means to communicate (maybe even a EventEmitter) via this provider between the two components.

hi,

I have the same goal and need to keep the popOver Open. have you find a solution?
my slack question base :

" I have a ion-range in my popOver Component. I simply want to get alert onChange and get the range value in the parent component who have create the popOver. How can i do this?

I probably know that is it possible if i communicate via a service in the middle but i want to find a light solution. I try @output decorator but how to catch the event in the parents? or another solution?"

But not suitable answer fo now.

could do it with events publish in the popover and events subscribe on the parent

Hi @ultradryan, I know this is a little old, but thought I’d share the solution with you none the less as I came across the same issue yesterday…

We already know that we can pass objects to the popover, so all we need to do is create and send an event emitter to the popover, which we can then emit from the popover and respond to in the parent.

In the parent…

export class HomePage {

	private showPopover() {

		let myEmitter = new EventEmitter< any >();
		myEmitter.subscribe(
			v=> console.log( `my emitter fired and returned a value of ${v}`)
		);

		let popover = this.popoverCtrl.create( MyPopoverComponent, {theEmitter: myEmitter} );
		
		popover.present({
			ev: event
		  });
	}
}

In the popover…

export class MyPopoverComponent {

	private _anEmitter: EventEmitter< any >;

	constructor( navParams: NavParams ) {
		this._anEmitter = navParams.data.theEmitter;
	}

	private myEventAction( somePassedArg: any ) {
		this._anEmitter.emit( somePassedArg );
	}

}

Lance :slight_smile:

3 Likes

I suggest to try Ionic Events