Search code examples
angulartypescriptangular5angular-directive

Create custom directive that will run a function on an event


In angularjs I had a directive:

export default angular.module('cd.enter', [])
    .directive('cdEnter', () => {
        return {
            link: (scope, element, attrs) => {
                element.bind("keydown", (event) => {
                    if (!event.shiftKey && event.which === 13) {
                        event.preventDefault();
                    }
                });

                element.bind("keyup", (event) => {
                    if (!event.shiftKey && event.which === 13) {
                        event.preventDefault();
                        scope.$apply(() => {
                            scope.$eval(attrs.cdEnter);
                        });
                    }
                });
            }
        }
    });

This would allow a newline inside a textarea with shift + enter and would then run a function if just enter was pressed.

How can I reproduce this in angular? The following will bind to the keyup and keydown events, but I need to know how to get the function, and then run it in the correct context.

import { Directive, Input, HostListener } from '@angular/core';

@Directive({
  selector: '[cdEnter]'
})
export class EnterDirective {
  @Input() cdEnter: Function;

  constructor() { }

  @HostListener('keydown', ['$event']) onKeyDown(event) {
    if (!event.shiftKey && event.which === 13) {
      event.preventDefault();
    }
  }

  @HostListener('keyup', ['$event']) onKeyUp(event) {
    if (!event.shiftKey && event.which === 13) {
      event.preventDefault();
      //How to perform the equivalent in Angular
      //scope.$apply(() => {
      //  scope.$eval(this.cdEnter);
      //});
    }
  }
}

Solution

  • You do not need the event.shiftKey and event.which. Angular provides a nice high level API for handling events in a declarative manner. You can just type keydown.shift.enter in the @HostBinding() args.

    import { Directive, Input, HostListener } from '@angular/core';
    
    @Directive({
      selector: '[cdEnter]'
    })
    export class EnterDirective {
      @Input() cdEnter: Function;
    
      constructor() { }
    
      @HostListener('keydown.shift.enter', ['$event'])
      onKeyUp(event: any) {
        event.preventDefault();
        this.cdEnter();
      }
    }
    

    Live demo