【问题标题】:"Trim" directive for angular 2 and reflect changes to ngModel角度 2 的“修剪”指令并反映对 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中的文本不受影响。

有什么建议吗?

【问题讨论】:

    标签: angular angular-directive angular2-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

            【讨论】:

              猜你喜欢
              • 2016-06-07
              • 2015-10-27
              • 2015-01-24
              • 2015-10-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-10-02
              • 2015-08-03
              相关资源
              最近更新 更多