web-dev-qa-db-ja.com

angular 2の「トリム」ディレクティブ、ngModelへの変更を反映

Angular 2ディレクティブを作成します。これは、ユーザーが入力フィールドに入力したテキストの最初と最後からのみスペースを開始するディレクティブです。

入力欄があります

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

および指令

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();
  }
}

これは正常に機能し、スペースを削除して入力フィールドのテキストを変更しますが、問題はngModel変数「fruit」の値が変更されず、先頭または末尾にスペースのあるテキストが含まれていることです。

OnChangeメソッドに以下を追加しようとしました

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

フォーム(ぼかし)を(ngModelChange)に変更しますが、ngModelのテキストは影響を受けません。

助言がありますか?

8
misterGrosar

https://github.com/anein/angular2-trim-directive を見ましたか?

それはあなたのユースケースに対処するようです

4
Vijay

モデル属性名の変更による混乱を避けるため。

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

例のCommonControllerは、onDestroyフックのサブジェクトをトリガーしてオブザーバブルのサブスクライブを解除する単なる基本クラスです。

@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());
      }
    });
  }

}

汎用的なトリムディレクティブを作成できます。これにより、ぼかしイベントだけでなく、提供するトリムイベントも生成されます。

@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

1年以上遅れていますが、試してみてください https://www.npmjs.com/package/ngx-trim-directive

これは、Angularが入力イベントをリッスンして、ビューからモデルへのバインディングを実現するという単純な事実に基づいています。

デモ: https://angular-86w6nm.stackblitz.io 、エディター: https://stackblitz.com/edit/angular-86w6nm

1
KingMario

@ErVipinSharma src/input-trim.directive.tsファイルを変更しました。このファイルは、上記のgithubへのリンクにあります。このファイルでは、メソッドを削除しました

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

と追加されたメソッド

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