11

我想创建 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();

并将表单 (blur) 更改为 (ngModelChange),但 ngModel 中的文本不受影响。

有什么建议么?

4

8 回答 8

18

避免混淆更改模型属性名称。

<input name="fruit" [(ngModel)]="fruit1" (change)="fruit1=fruit1.trim()"/>
于 2018-06-04T12:18:53.180 回答
5

你看过https://github.com/anein/angular2-trim-directive吗?

似乎它会解决您的用例

于 2017-04-20T18:25:26.267 回答
3

示例中的 CommonController 只是触发 onDestroy 钩子中的主题以取消订阅 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());
      }
    });
  }

}

您可以创建通用修剪指令,这将不仅为模糊事件进行修剪,而且对您将提供的任何事件进行修剪:

@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());
      }
    });
  }
于 2019-05-23T10:43:20.353 回答
1

虽然晚了一年多,但你可能想试试https://www.npmjs.com/package/ngx-trim-directive

它基于一个简单的事实,即 Angular 监听输入事件以实现视图到模型的绑定。

演示:https ://angular-86w6nm.stackblitz.io ,编辑:https ://stackblitz.com/edit/angular-86w6nm

于 2018-10-16T16:08:47.563 回答
1

以下指令可以与 Reactive-Forms 一起使用来修剪所有表单字段:

@Directive({
  selector: '[formControl], [formControlName]',
})
export class TrimFormFieldsDirective {
  @Input() type: string;

  constructor(@Optional() private formControlDir: FormControlDirective, 
              @Optional() private formControlName: FormControlName) {}

  @HostListener('blur')
  @HostListener('keydown.enter')
  trimValue() {
    const control = this.formControlDir?.control || this.formControlName?.control;
    if (typeof control.value === 'string' && this.type !== 'password') {
      control.setValue(control.value.trim());
    }
  }
}
于 2020-06-19T06:22:05.600 回答
0

如果您使用https://github.com/anein/angular2-trim-directive<input trim="blur" ...>它将允许中间空间。

在此处输入图像描述

于 2022-02-02T16:36:58.673 回答
0

@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
}
于 2018-01-08T06:52:48.013 回答
0

我真的很喜欢这个指令,因为它几乎自动适用于所有内容:

import { Directive, forwardRef, HostListener } from '@angular/core';
import { DefaultValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
const TRIM_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => TrimValueAccessorDirective),
  multi: true,
};
/**
 * The trim accessor for writing trimmed value and listening to changes that is
 * used by the {@link NgModel}, {@link FormControlDirective}, and
 * {@link FormControlName} directives.
 */
@Directive({
  // eslint-disable-next-line @angular-eslint/directive-selector
  selector: `
 input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.ng-trim-ignore)[formControlName],
 input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.ng-trim-ignore)[formControl],
 input:not([type=checkbox]):not([type=radio]):not([type=password]):not([readonly]):not(.ng-trim-ignore)[ngModel],
 textarea:not([readonly]):not(.ng-trim-ignore)[formControlName],
 textarea:not([readonly]):not(.ng-trim-ignore)[formControl],
 textarea:not([readonly]):not(.ng-trim-ignore)[ngModel],
 :not([readonly]):not(.ng-trim-ignore)[ngDefaultControl]'
 `,
  providers: [TRIM_VALUE_ACCESSOR],
})
export class TrimValueAccessorDirective extends DefaultValueAccessor {
  @HostListener('input', ['$event.target.value'])
  ngOnChange = (val: string) => {
    this.onChange(val.trim());
  };
  @HostListener('blur', ['$event.target.value'])
  applyTrim(val: string) {
    this.writeValue(val.trim());
  }
  writeValue(value: any): void {
    if (typeof value === 'string') {
      value = value.trim();
    }
    super.writeValue(value);
  }
}

从这里开始:https ://medium.com/@rm.dev/angular-auto-trim-your-input-string-using-angular-directive-5ae72b8cee9d

于 2021-07-08T18:11:57.877 回答