Hectore
Hectore

Reputation: 25

angular keyup event does not trigger on child component, but only on parent instead

I created a component that i wish to have multiple versions of it in my app, since i want to keep all the logic in only one place, i created a ParentComponent where all my code resides.

But angular dont inherit component annotations, so i created also a "TemplateComponent", to prevent code duplication. The TemplateComponent holds the input, but it's the ParentComponent that handles the events from the input. That way, every ChildComponent, inherits ParentComponent for the logic, and it's template is a instance of TemplateComponent.

The big deal, is that when i try to listen to keyup event on the input inside TemplateComponent, the click event is being called on ChildComponent, who dont have any inputs or controls.

I've tryed to pass an event binding to template component to connect the keyup input, but it never triggers.

There's a HostListener on the ChildComponent, just to debug that the event is only being triggered there. And it's not that that's causing the event to stop there.

Is there a way to tell angular that the keydown event must be called inside the template component, or another way of linking everything toghether ?

I got a working plunker, it's pretty much self-explanatory:

https://plnkr.co/edit/e4U6DB4d47ULpLppHd4H?p=preview

But also the code:

ParentComponent:

import {Component, NgModule, VERSION} from '@angular/core'

@Component({
  selector: 'app-parent',
  template: `
    <ng-content></ng-content>
  `,
})
export class ParentComponent {

  printText = 'Not yet';

  constructor() {
  }

  inputKeyDownEnter(event: any) {
    this.printText = 'KeyDown OK!';
  }

  clearButtonClick(event: any) {
    this.printText = "Clear button click!";
  }
}

ChildComponent:

import {Component, HostListener} from '@angular/core';
import {ParentComponent} from './parent.component';

@Component({
  selector: 'app-child',
  template: `
    <div>{{printText}}</div>
    <app-custom-template
      (inputKeyDownEnter)="inputKeyDownEnter"
      (clearButtonClick)="clearButtonClick"
    >
    </app-custom-template>
  `,
})
export class ChildComponent extends ParentComponent {

  constructor() {
    super();
  }

  @HostListener('keydown.enter', ['$event'])
  onKeyDownChild(event: any) {
    console.log('Only here :( !');
  }

}

TemplateComponent:

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

@Component({
  selector: 'app-custom-template',
  template: `
    <input 
      type="text"
      name="my_text"
      (keyup.Enter)="inputKeyDownEnter.emit($event)"
      />
    <button
      type="button"
      (click)="clearButtonClick.emit($event)">Clear</button>
  `,
})
export class CustomTemplateComponent {

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

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

  constructor() {
  }

}

Upvotes: 2

Views: 3536

Answers (1)

yurzui
yurzui

Reputation: 214047

You should call method

(inputKeyDownEnter)="inputKeyDownEnter($event)"
                                      ^^^^^^^^^

Plunker

Upvotes: 3

Related Questions