Angular 4 Event Emitter not Emitting

14.8k Views Asked by At

So I have an event emitter working just fine. In my child, I call a function:

(click)="EnterEditMode()

which fires:

EnterEditMode(){ 
    this.enterEdit.emit(null);
  }

In my parent, I then:

  enterEdit(){
    console.log("got some text");
  }  

This works flawlessly. But now I want to add a second output right next to it. So in the child, I call:

SaveChanges();

Which triggers a function:

SaveChanges() {
    this.saveChanges.emit(null);
    console.log("save");
  }

When I call this, the console log is triggered but the emit is not triggered. My parent has a function that is thus never called.

saveChanges() {
    console.log("saving changes");
    this.editing ? this.editing = false : this.editing = true;
  }

I really can't see what I'm doing wrong and have tried to trouble shoot but I'm getting no errors, just the console log that the "SaveChanges()" has been called. Am I missing something about emitters?

Edit to show my event emitters

In my child component I:

@Output() enterEdit = new EventEmitter<any>();
@Output() saveChanges = new EventEmitter<any>();

Again, enterEdit works but saveChanges does not...

4

There are 4 best solutions below

1
On BEST ANSWER

So this was due to a fundamental misunderstanding of how Output Emitters work in Angular.

Wrong assumption Simply triggering an emitter would force my controller to react.

Solution In my html file, I have to add the listener to an element and then pass the event from the html to the controller. This triggers the controller to do what ever the function is supposed to do.

In my .html file I need to add (saveChanges)='saveChanges($event)' to my custom component. This works.

0
On

Check list

Check that all the following is met (examples below):

  1. EventEmitter is an @Output.
  2. The emit function is reachable.
  3. You are calling the function in the template.

Examples

  1. EventEmitter is an @Input:
@Component({
  selector: `TempratureCalculator`
  // ...
})
export class TempratureCalculator {
  @Input() tempratureChange = new EventEmitter<float>();

  change(t: float) {
    this.tempratureChange.emit(t);
  }
}

@Component({
  // ...
  template: `<TempratureCalculator (tempratureChange)="change(t)"></TempratureCalculator>
`
})
export class AppComponent {
  change(t: float) {}
}
  1. Check that emit is reachable:
// before
this.tempratureChange.emit(/* ... */);

// after
debugger;
this.tempratureChange.emit(/* ... */);

This will pause and open the debugger in the browser just before emitting. If that didn't happen then the emit call is unreachable.

  1. Passing the function instead of calling it:
<!-- Wrong, Doesn't work -->
<TempratureCalculator (tempratureChange)="change"></TempratureCalculator>

<!-- This works -->
<TempratureCalculator (tempratureChange)="change(t)"></TempratureCalculator>

This is a community wiki answer, feel free to extend the answer

0
On

In my case, just the name of event emitter have to match the one in the parent In children component controller: @Output('emittername') emitter In parent template: (emittername)="handler($event)". Silent compilation error can be a drama.

0
On

In my particular case, I was experiencing this issue without warnings or messages.

My misunderstanding was the following:

<app-child [someObject]="currentObject" (emitEventFunction)="saveChange($event)">

In my template tag, I placed the name of my function that emits an event, emitEventFunction(), instead of placing the object I declared with the @Output() decorator. This meant that while I was trying to get the function emitEventFunction() called whenever the saveChange() function was called in my child component, Angular was actually looking for an object called emitEventFunction.

The solution, naturally, was to find what I had declared as my output:

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

And use that instead:

<app-child [someObject]="currentObject" (entryChange )="saveChange($event)">