角度 2 的“修剪”指令并反映对 ngModel 的更改

Posted

技术标签:

【中文标题】角度 2 的“修剪”指令并反映对 ngModel 的更改【英文标题】:"Trim" directive for angular 2 and reflect changes to ngModel 【发布时间】:2017-09-09 07:21:28 【问题描述】:

我想创建 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中的文本不受影响。

有什么建议吗?

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

【参考方案2】:

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

似乎它可以解决您的用例

【讨论】:

感谢您的回答!该目录仅部分解决了我的问题。它删除了所有空格,我需要的是这样的指令,它允许用户输入带有多个单词的文本,例如“This is example”,并从字符串的开头和结尾修剪空格。 我对 angular2-trim-directive 做了一些修改(我删除了 @HostListener( 'input', [ '$event.target.value' ]) 方法并添加了粘贴事件监听器),它就像我需要的那样工作。 @Vijay 我会接受你的评论作为答案。 @misterGrosar 你说的“添加粘贴事件监听器”是什么意思???您在哪个文件中更改了,或者您可以共享您更改的代码???【参考方案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());
      
    );
  

【讨论】:

【参考方案4】:

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

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

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

【讨论】:

遗憾的是,它与 Material Angular 不兼容。 旁注:它与 angular v2.4 不兼容。 (将 renderer2 更改为 renderer 就可以了)。【参考方案5】:

以下指令可以与 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());
    
  

【讨论】:

【参考方案6】:

@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

【讨论】:

【参考方案7】:

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

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

【讨论】:

以上是关于角度 2 的“修剪”指令并反映对 ngModel 的更改的主要内容,如果未能解决你的问题,请参考以下文章

在 Angular2 ngModel 值未在自定义指令的 onBlur 事件上更新

使用 formControlName 和 ngModel 的角度 6 警告

用于 textarea 的 ngModel 不能在角度 2 中工作

如何在角度指令 4 中使用范围

在角度 2+ 中为 ngmodel 设置动态变量参考

当有ngModel时,检查角度2中的单选按钮