How to restrict Special character in material input
Asked Answered
S

3

10

I have a material input control, i have restrict the special character while user enter, but when type some words in any editor and copy and paste the words with special character, which is not working.

I have write the directive for that to prevent special character,but can one provide the better solution restrict in copy paste.

app.component.html:

<form class="example-form">
  <mat-form-field class="example-full-width">
    <input matInput specialIsAlphaNumeric placeholder="Favorite food" value="Sushi">
  </mat-form-field>

  <mat-form-field class="example-full-width">
    <textarea matInput placeholder="Leave a comment"></textarea>
  </mat-form-field>
</form>

directive:

import { Directive, HostListener, Input } from '@angular/core';
@Directive({
    selector: '[specialIsAlphaNumeric]'
})
export class SpecialCharacterDirective {

    regexStr = '^[a-zA-Z0-9_]*$';
    @Input() isAlphaNumeric: boolean;

    @HostListener('keypress', ['$event']) onKeyPress(event) {
        return new RegExp(this.regexStr).test(event.key);
    }

}

demo see here:

https://stackblitz.com/edit/angular-cijbqy-biwrck?file=app%2Finput-overview-e[stackblit][1]

Steps to reproduce:

type it special character which is not allowed : working fine. while copy paste wit allows special character

Stoker answered 19/7, 2018 at 17:17 Comment(2)
try onchange or onChange instead of keypressCentare
@Hussain I have tried OnChange as well as paste events all gets triggered,but it allow to paste.if your solution , please update here https://stackblitz.com/edit/angular-cijbqy-biwrck?file=app/specialChracter.directive.tsStoker
C
29

Try Like this:

stackblitz example

import { Directive, HostListener, ElementRef, Input } from '@angular/core';
@Directive({
  selector: '[specialIsAlphaNumeric]'
})
export class SpecialCharacterDirective {

  regexStr = '^[a-zA-Z0-9_]*$';
  @Input() isAlphaNumeric: boolean;

  constructor(private el: ElementRef) { }


  @HostListener('keypress', ['$event']) onKeyPress(event) {
    return new RegExp(this.regexStr).test(event.key);
  }

  @HostListener('paste', ['$event']) blockPaste(event: KeyboardEvent) {
    this.validateFields(event);
  }

  validateFields(event) {
    setTimeout(() => {

      this.el.nativeElement.value = this.el.nativeElement.value.replace(/[^A-Za-z ]/g, '').replace(/\s/g, '');
      event.preventDefault();

    }, 100)
  }

}
Candescent answered 19/7, 2018 at 17:48 Comment(6)
@MohamedSahir, if you want the original answer is: #47385452 its includes cut and copy too.Clower
@UnluckyAj which is working as expected for input field,when work with multiinput controls , which has splitted the character as 1 tab and empty string as another tab while copy paste this text DDD@# , so it takes DDD as first and @# replace with '' not working as expected. attached a screenshot and create a demoStoker
@UnluckyAj this solution suffers from a flash in the UI which is fixed in my solution belowContumely
Thanks for StackBlitz!Egocentrism
It works but it is not allowing space between char and i need the space?Unionize
all space in regex. @MoHalemCandescent
C
3

The following approach works without using the setTimeout call, which means there is no flashing of special characters in the input control when the other response by Aashish K Jha is used

import { Directive, HostListener, ElementRef, Input } from '@angular/core';
@Directive({
  selector: '[specialIsAlphaNumeric]'
})

export class SpecialCharacterDirective {

  regexStr = '^[a-zA-Z0-9_]*$';
  @Input() isAlphaNumeric: boolean;

  constructor(private el: ElementRef) { }


  @HostListener('keypress', ['$event']) onKeyPress(event) {
    return new RegExp(this.regexStr).test(event.key);
  }

  @HostListener('paste', ['$event']) blockPaste(event: ClipboardEvent) {
    this.validateFields(event);
  }

  validateFields(event: ClipboardEvent) {
    event.preventDefault();
    const pasteData = event.clipboardData.getData('text/plain').replace(/[^a-zA-Z0-9 ]/g, '');
    document.execCommand('insertHTML', false, pasteData);
  }
}
Contumely answered 16/5, 2019 at 3:14 Comment(1)
the absence of the setTimeout means there is no flash when the users pastes their content, a much improved outcome than simply waiting 100msContumely
L
1

You can use Ng Knife utility

  1. Import NgKnifeModule

    ... 
    import { NgKnifeModule } from 'ng-knife';
    ...
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        NgKnifeModule
      ],
      ...
    });
    export class AppModule { }
    
  2. Using it:

    <!-- Aphanumeric -->
    <input knifeAlphanumeric type="text">
    
Lotte answered 27/8, 2018 at 15:7 Comment(1)
This is by far the cleanest solution out there. Why reinvent the wheel if someone else has already done it!? Thx for this!Felicity

© 2022 - 2024 — McMap. All rights reserved.