Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

235
Vistas
Proper way to use Angular EventEmitter

In my simplified scenario there is a parent component, which contains all the business logic.

The parent creates a child component which is only responsible to display a list of buttons.

I want to handle the click events for such buttons in the parent, but, using the suggested EventEmitter pattern I'm forced to use a useless switch case in the parent, in order to detect which button is pressed.

It would be much easier to directly pass the callbacks as input of the child, but I think it's not a good practice. Also these callbacks, as far as I can see, are executed in the context of the child, which is not the desired outcome.

Am I missing something? Is there a better way to achieve my needs? Or I'm completely approaching the problem in a wrong way?

The parent:

import { Component } from "@angular/core";

@Component({
  selector: "parent",
  template: ` <child
      [buttons]="buttons"
      (click)="onButtonClick($event)"
    ></child>
    <span>{{ description }}</span>`
})
export class ParentComponent {
  description = "";
  buttons = ["foo", "bar", "baz"];

  onButtonClick(button: string) {
    switch (button) {
      case "foo":
        this.description = "Calling foo()";
        this.foo();
        break;
      case "bar":
        this.description = "Calling bar()";
        this.bar();
        break;
      case "baz":
        this.description = "Calling baz()";
        this.baz();
        break;
    }
  }

  foo() {}
  bar() {}
  baz() {}
}

The child:

import { Component, EventEmitter, Input, Output } from "@angular/core";

@Component({
  selector: "child",
  template: ` <span *ngFor="let button of buttons">
    <button (click)="onClick(button)">{{ button }}</button>
  </span>`
})
export class ChildComponent {
  @Input() buttons: string[];

  @Output() click = new EventEmitter<string>();

  onClick(button: string) {
    this.click.emit(button);
  }
}

And a working sandbox.

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

You could think about providing the callbacks within an object array instead of the string array.

Edited Sandbox: https://codesandbox.io/s/cocky-brahmagupta-ueg4nv

The Parent

import { Component } from "@angular/core";

@Component({
  selector: "parent",
  template: ` <child
      [buttons]="buttons"
    ></child>
    <span>{{ description }}</span>`
})
export class ParentComponent {
  description = "";
  buttons = [
    { name: "foo", callback: () => { this.description = "Calling foo()" } },
    // bar
    // baz
  ];
}

The child

@Component({
  selector: "child",
  template: ` <span *ngFor="let button of buttons">
    <button (click)="button.callback()">{{ button.name }}</button>
  </span>`
})
export class ChildComponent {
  @Input() buttons: MyButton[];
}

The interface

interface MyButton {
  name: string,
  callback: () => void;
}
about 4 years ago · Juan Pablo Isaza Denunciar

0

You can emit what-ever

//parent

@Component({
  selector: "parent",
  template: ` <child
      [buttons]="buttons" (click)="$event()"
    ></child>
    <span>{{ description }}</span>`
})
export class ParentComponent {
  description = "";
  buttons = [
    { name: "foo", callback: this.foo},
    { name: "bar", callback: this.bar},
    { name: "baz", callback: this.baz},
  ];
  foo(){}
  bar(){}
  baz(){}
}

//child

@Component({
  selector: "child",
  template: ` <span *ngFor="let button of buttons">
    <button (click)="onClick(button)">{{ button.name }}</button>
  </span>`
})
export class ChildComponent {
  @Input() buttons: any[];

  @Output() click = new EventEmitter<any>();

  onClick(button: any) {
    this.click.emit(button.callback);
  }
}

Update Sound "bizarro" pass a function and execute using function(), but we need think that a function is only an object.

Imagine you define two functions

function1(){console.log("I'm function 1")}
function2(){console.log("I'm function 1")}

In an event click we call to a function

click()
{
   const mainFunction=this.function1
   mainFunction() //execute the function1
}

or according a variable

click()
{
   const mainFunction=this.condicion?this.function1:this.function2
   mainFunction() //execute the function1 or the function2 
                  //if condition is true or false
}

The variables,object,arrays,functions... are physical stored in a memory position. the "name" of the variable, object, function... are only a "pointer" to this memory.

If we want, we could in the answer write

    <child [buttons]="buttons" (click)="executeFunction($event)"></child>

   executeFunction(mainFunction:any)
   {
         mainFunction()
   }

If we want we can type the function to give more clearity if all our function has no argument and no return anything, instead use this uggly "any" use

   executeFunction(mainFunction:()=>void)
   {
         mainFunction()
   }

And

@Output() click = new EventEmitter<()=>void>();
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda