Munna Babu
Munna Babu

Reputation: 5756

Event handler performance issue in Angular 4 / 5

Sorry if my question is silly, but we are facing a latency issue in our application. KEYPRESS event handler is the culprit. We are using this below directive in the entire application. It checks KeyPress through HostListener. When key pressed, this directive checks the value with regexp and does preventDefault if condition is false.

private regexMap = { // add your own
    '999': /^([0-9]){0,3}$/g,
    '9999': /^([0-9]){0,4}$/g,
    ...
    ...
}

@HostListener('keypress', [ '$event' ])
public nInput(event: KeyboardEvent) {
    // Allow Backspace, tab, end, and home keys
    if (this.specialKeys.indexOf(event.key) !== -1) {
        return;
    }
    this.pattern = this.regexMap[this.validationFormat];
    const current: string = this.el.nativeElement.value;
    const next: string = current.concat(event.key);
    if (next && !String(next).match(this.pattern)) {
        event.preventDefault();
    }
}

I am not sure how to fix this issue. Will debounceTime fix this issue? I am not sure how to add debounce to this method. Please someone help me to solve this issue.

Upvotes: 5

Views: 1677

Answers (2)

Abhijit Kar ツ
Abhijit Kar ツ

Reputation: 1732

Assuming that you want to keep using keypress events, which fires for every keypress by user

Try optimizing the Regex:

i.e remove g and brackets from regex. Make the regex like this -

/^[0-9]{0,3}$/

For more tricks refer: Regex Optimizations

Websites are particularly bad with Streaming Validation (i.e. Validating text, live!)

  1. If it is okay to not have a streaming validation check, then use focus lost event, i.e. run your code after focus is lost from text field.
  2. Or better yet, do it like Angular documentation suggests Email Validation Demo, don't correct the mistakes, just point it out, user will correct it.

Upvotes: 1

Munna Babu
Munna Babu

Reputation: 5756

Fixed issue with DebounceTime :) just added debounce time with help Subject. Basically when user enter something it stop all action, then send EVENT(key pressed value) to SUBJECT and In subject debounce Time wait 300ms and then do function test

    private keyPressed = new Subject();
    private subscription: Subscription;
    private pattern: RegExp;
    private regexMap = { // add your own
     '999': /^([0-9]){0,3}$/g,
     '9999': /^([0-9]){0,4}$/g,
      ...
      ...
   }
    private specialKeys: string[] = ['Backspace', 'Tab', 'End', 'Home'];

    constructor(private el: ElementRef) {
    }

    public ngOnInit() {
        this.subscription = this.keyPressed.pipe(debounceTime(300)).subscribe(
            (event) => this.checkRegExpression(event)
        );
    }

    public ngOnDestroy() {
        this.subscription.unsubscribe();
    }

    @HostListener('keypress', ['$event']) public nInput(event: KeyboardEvent) {
        event.preventDefault();
        event.stopPropagation();
        this.keyPressed.next(event);
    }

    private checkRegExpression(event) {
        if (this.specialKeys.indexOf(event.key) !== -1) {
            return;
        }
        this.pattern = this.regexMap[this.validationFormat];
        const current: string = this.el.nativeElement.value;
        const next: string = current.concat(event.key);
        if (next && !String(next).match(this.pattern)) {
            event.preventDefault();
        }
    }

Upvotes: 3

Related Questions