web-dev-qa-db-fra.com

Directive "Trim" pour angular 2 et reflète les modifications apportées à ngModel

Je veux créer Angular 2 qui ne confirmera les espaces qu'à partir du début et de la fin du texte que l'utilisateur a tapé dans le champ de saisie.

J'ai un champ de saisie

<input trim name="fruit" [(ngModel)]="fruit"/>

et directive

import {Directive, ElementRef} from "@angular/core";

@Directive({
  selector: 'input[trim]',
  Host: {'(blur)': 'onChange($event)'}
})

export class TrimWhiteSpace {

  constructor(private cdRef:ChangeDetectorRef, private el: ElementRef){}

  onChange($event:any) {
    let theEvent = $event || window.event;
    theEvent.target.value = theEvent.target.value.trim();
  }
}

qui fonctionne bien, supprime les espaces et modifie le texte dans le champ de saisie, mais le problème est que la valeur de la variable ngModel "fruit" n'est pas modifiée et qu'elle contient toujours du texte avec des espaces au début ou à la fin.

J'ai également essayé d'ajouter ce qui suit à la méthode onChange

this.el.nativeElement.value = theEvent.trim();
this.cdRef.detectChanges();

et changez la forme (flou) en (ngModelChange), mais le texte dans ngModel n'est pas affecté.

Aucune suggestion?

8
misterGrosar

Avez-vous regardé https://github.com/anein/angular2-trim-directive ?

On dirait que cela répondrait à votre cas d'utilisation

4
Vijay

pour éviter toute confusion en changeant le nom d'attribut du modèle.

<input name="fruit" [(ngModel)]="fruit1" (change)="fruit1=fruit1.trim()"/>
10
Shreesha

CommonController dans l'exemple est juste une classe de base qui déclenche le sujet du hook onDestroy à se désabonner de l'observable.

@Directive({
  selector: '[appTrimOnBlur]'
})
export class TrimOnBlurDirective extends CommonController implements OnInit {

  constructor(private elementRef: ElementRef,
              @Self() private ngControl: NgControl) {
    super();
  }

  ngOnInit(): void {
    fromEvent(this.elementRef.nativeElement, 'blur').pipe(
      takeUntil(this.unsubscribeOnDestroy)
    ).subscribe(() => {
      const currentValue: string = this.ngControl.value.toString();
      const whitespace: string = ' ';
      if (currentValue.startsWith(whitespace) || currentValue.endsWith(whitespace)) {
        this.ngControl.control.patchValue(currentValue.trim());
      }
    });
  }

}

Vous pouvez créer une directive de découpage générique, qui effectuera le découpage non seulement pour un événement de flou, mais pour tout événement que vous fournirez:

@Input() public trimEventName: string = 'blur';

  constructor(private elementRef: ElementRef,
              @Self() private ngControl: NgControl) {
    super();
  }

  ngOnInit(): void {
    fromEvent(this.elementRef.nativeElement, this.trimEventName).pipe(
      takeUntil(this.unsubscribeOnDestroy)
    ).subscribe(() => {
      const currentValue: string = this.ngControl.value.toString();
      const whitespace: string = ' ';
      if (currentValue.startsWith(whitespace) || currentValue.endsWith(whitespace)) {
        this.ngControl.control.patchValue(currentValue.trim());
      }
    });
  }
2
Artyom Krasnyuk

Bien qu'il soit plus d'un an en retard, mais vous voudrez peut-être essayer https://www.npmjs.com/package/ngx-trim-directive

Il repose sur un simple fait que Angular écoute l'événement d'entrée pour donner naissance à la liaison vue-modèle.

Démo: https://angular-86w6nm.stackblitz.io , éditeur: https://stackblitz.com/edit/angular-86w6nm

1
KingMario

@ErVipinSharma J'ai changé le fichier src/input-trim.directive.ts, que vous pouvez trouver dans le lien ci-dessus vers le github. Dans ce fichier, j'ai supprimé la méthode

@HostListener( 'input', ['$event.type', '$event.target.value'] )
onInput( event: string, value: string ): void {
    this.updateValue( event, value );
}

et méthode ajoutée

@HostListener('paste', ['$event', '$event.target'])
onPaste($event: any, target: any) {
    // do something when on paste event happens
}
0
misterGrosar