Search code examples
javascriptangulardecoratoreventemitter

Angular 2 eventEmitter dosen't work


I need to make something simple, I want to display a dialog when I click on an help icon.

I have a parent component:

@Component({
  selector: 'app-quotation',
  templateUrl: './quotation.component.html'
})
export class QuotationComponent implements OnInit {

  public quotation: any = {};
  public device: string;
  public isDataAvailable = false;

  @Output() showPopin: EventEmitter<string> = new EventEmitter<string>();

  constructor(private quotationService: QuotationService,
              private httpErrors: HttpErrorsService,
              private popinService: PopinService) {}

  moreInfo(content: string) {
      console.log('here');
    this.showPopin.emit('bla');
  }
}

And his html:

<ul>
    <li *ngFor="let item of quotation.HH_Summary_TariffPageDisplay[0].content">
        <label></label>
        <i class="quotation-popin" (click)="moreInfo()"></i>
        <div class="separator"></div>
    </li>
</ul>

My popin component:

@Component({
  selector: 'app-popin',
  templateUrl: './popin.component.html',
  styleUrls: ['./popin.component.scss']
})
export class PopinComponent implements OnInit {

  public popinTitle: string;
  public popinContent: string;
  public hidden: boolean = true;

  constructor() { }

  openPopin(event):void {
    console.log("here");
    this.hidden = false;
  }

}

His HTML:

<div class="card-block popin-container" (showPopin)="openPopin($event)" *ngIf="!hidden">
  <div class="card">
    <div class="popin-title">
      {{ popinTitle }}
      <i class="icon icon-azf-cancel"></i>
    </div>
    <div class="popin-content">
      {{ popinContent }}
    </div>
  </div>
</div>

My parent component is loaded in a router-outlet and my popin is loaded on the same level than the router-outlet, like this:

<app-nav-bar></app-nav-bar>
<app-breadcrumb></app-breadcrumb>
<div class="container">
  <router-outlet></router-outlet>
</div>

<app-popin></app-popin>

My problem is the eventEmitter doesn't work and i don't know why, someone can explain me ?

thx,

regards


Solution

  • EventEmitters only work for direct Parent-Child component relationships. You do not have this relationship with the components you are describing here.

    In a parent-child relatonship, we will see the child's component element within the parent's template. We do not see this in your example.

    You have two options:

    1. Refactor to use a parent-child relationship
    2. Use a service for communication

    If you go with option 2, the service should just contain an observable that one component calls next on, and the other component subscribes to.

    @Injectable()
    export class PopinService {
      showPopin = new ReplaySubject<string>(1); 
    }
    

    Inject this in QuotationComponent and modify moreInfo

      moreInfo(content: string): void {
        this.popinService.showPopin.next('bla' + content);
      }
    

    In PopinComponent inject the popinService and add the following:

    ngOnInit() {
    
      this.popinService.showPopin.subscribe(content => {
        this.hidden = false;
        this.popinContent = content;
      });
    
    }