abhilash reddy
abhilash reddy

Reputation: 1586

Event bubling using hostevent listener

I have built a directive which subscribes the keyboard event using host event listener. When escape key is pressed I am firing an output event like this

    @HostListener('document:keyup', ['$event'])
    handleKeyboardEvent(kbdEvent: KeyboardEvent) {
       if (kbdEvent.keyCode === 27) {
            this.CloseEvent.emit();
       }
    }

I have this directive for child elements. When escape key is pressed I want to fire the output event only for the newly subscribed elements. The problem is when I click on escape key the event is fired based on hierarchical order. I have made a demo here: https://plnkr.co/edit/FfnHAtxl2zcHsu0JilKt

Steps to reproduce:

  1. Add Multiple Child Elements
  2. Click On Escape it close all elements

Expected behavior:

  1. When Escape key is clicked on the last added child element event needs to be fired

Upvotes: 0

Views: 113

Answers (1)

Poul Kruijt
Poul Kruijt

Reputation: 71911

One way to do it is to send the KeyboardEvent with the close event. You can then check if the event has defaultPrevented set to true, if not, execute the deletion and preventDefault.

I've made some optimizations. You can just use the 'document:keyup.ESC' binding, and you can immediately set (close) and it will use the CloseDirective

plnkr

my-app

@Component({
  selector: 'my-app',
  template: `
  <h4>Add Multiple Child And Click On Escape key</h4><br>
    <div *ngFor="let child of childArray;let i = index">
      <div style="display:flex;flex-direction:row">
          <my-chid (close)="onClose($event)" [index]="child"></my-chid>
          <button (click)="deleteChild(i)">Delete</button>
      </div>
    </div>
    <button (click)="addChild()">Add Child</button>
  `,
})
export class App {

  childArray: any[] = [];

  addChild(): void {
    this.childArray.push(this.childArray.length);
  }

  onClose(event: KeyboardEvent): void {
    if (!event.defaultPrevented) {
      event.preventDefault();
      this.deleteChild(this.childArray.length - 1);
    }
  }

  deleteChild(index: number): void {
    this.childArray.splice(index, 1);
  }
}

my-child

@Component({
  selector: 'my-chid',
  template: `
    <div>
       I am child {{index}}
    </div>
  `,
})
export class MyChild {

  @Input()
  public index: number; 

}

close directive

@Directive({
    selector: '[close]'
})
export class CloseDirective {

    @Output() close: EventEmitter<KeyboardEvent> = new EventEmitter<KeyboardEvent>();

    @HostListener('document:keyup.ESC', ['$event'])
    handleKeyboardEvent(kbdEvent: KeyboardEvent) {
      this.close.emit(kbdEvent);
    }
}

Upvotes: 1

Related Questions