【问题标题】:How to mask value in custom control如何在自定义控件中屏蔽值
【发布时间】:2017-10-05 03:51:28
【问题描述】:

如何在输入中显示转换后的值(例如“1(234)567-890”),而没有转换后的值('1234567890')?

是否可以为maskInputElmaskInput 分别设置值?

我有模板:

   <input #maskInputEl class="spacer" [type]="type"
   [formControl]="maskInput"/>

和自定义组件:

export class MaskInputComponent implements ControlValueAccessor, OnInit, OnDestroy {
    @ViewChild('maskInputEl') public maskInputEl: ElementRef;

    @Input() public mask: any[];

    public maskInput = new FormControl();

    private _oldValue: string = '';

    public ngOnInit(): void {
        this.maskInput.valueChanges
            .subscribe((value: string) => {
                    let valid = this.isValidValueByMask(value, this.mask);
                    if (valid) {
                        this._oldValue = value;
                    } else {
                        value = this._oldValue;
                    }

                    this._onChangeCallback(value);
                    this.onChange.emit(value);

                    this.maskInputEl.nativeElement.value = value; 
                },
                (err) => console.warn(err)
            );
    }

    public toggleActive(value) {
        //
    }

    public registerOnChange(fn: any): void {
        this._onChangeCallback = fn;
    }

    public registerOnTouched(fn: any): void {
        this._onTouchedCallback = fn;
    }

    public _onChangeCallback: Function = (_: any) => {
        //
    }

    public _onTouchedCallback: Function = (_: any) => {
        //
    }

    public makeActive() {
        this.maskInputEl.nativeElement.focus();
    }

    public writeValue(value: string): void {
        this.maskInput.setValue(value);
    }

    public ngOnDestroy(): void {
        //
    }

    private isValidValueByMask(value: string, mask: RegExp[]): boolean {
        //
    }
}

【问题讨论】:

    标签: forms angular angular2-forms angular2-formbuilder reactive-forms


    【解决方案1】:

    是的,这是可能的。我为自己的项目做了类似的事情,我想创建一个MoneyFieldComponent,它返回一个以美分为单位的值,但允许用户以美元和美分输入他们的货币价值。

    基本概念是您的组件必须存储原始值,但是,您在文本字段中显示格式化的值。此外,当用户与您的文本字段交互时,您会使用原始值更新组件的“内部值”。

    请注意,您不应该使用 ngModel 来更新您的文本字段 - ngModel 有一些异步行为会在这些情况下造成严重破坏 - 您可以使用原始 javascript 完成相同的操作(或者在我的情况下,我使用了 FormControl) .

    示例:

    @Component({
      selector: 'ec-money-field',
      template: `
          <md-input-container *ngIf="editMode">
              <input #input mdInput class="value" type="text"
                     (input)="updateInnerValue(input.value)"
                     (blur)="formatTextValue()"
                     [formControl]="control" />
          </md-input-container>
      `,
      providers: [
        {provide: NG_VALUE_ACCESSOR, multi: true, useExisting: forwardRef(() => MoneyFieldComponent)},
      ]
    })
    export class MoneyFieldComponent implements OnInit, ControlValueAccessor {
    
      private valueInCents = 0;
      control = new FormControl(0);
    
      private onChange: Function = (_: any) => {};
      private onTouch: Function = (_: any) => {};
    
      constructor() { }
    
      @Input()
      get value(): number {
        return this.valueInCents;
      };
    
      // if you update the component by using the value property,
      // propagate that change to the text field    
      set value(newValueInCents: number) {
        this.valueInCents = newValueInCents;
        this.control.setValue(centsToDollars(newValueInCents));
      }
    
      ngOnInit() {
      }
    
      // convert the masked value - i.e. what the user types
      // into the actual numerical value that will be stored
      // You'll have to provide your own conversion function 
      // to convert the user typing 1(855) 555 1234 to 1865551234
      updateInnerValue(dollarValueString: string) {
        this.valueInCents = dollarsToCents(dollarValueString);
        this.onChange(this.valueInCents);
      }
    
      formatTextValue() {
        this.value = this.value;
      }
    
      writeValue(newValue: number): void {
        this.value = newValue;
      }
    
      registerOnChange(fn: any): void {
        this.onChange = fn;
      }
    
      registerOnTouched(fn: any): void {
        this.onTouch = fn;
      }
    }
    

    请注意,以上是该组件的简化版本。 The full version can be found on Github.

    【讨论】:

    • 我需要相反的,即用户输入清除数据并使用掩码输入转换该数据
    • 但您仍然存储“清除数据”对吗?如果是这样,这是相同的基本概念 - 在用户键入后,您使用格式化值更新 formField,但您将实际值存储在组件中。如果您仅将 formField 更新为模糊时的格式化值,则更容易实现 - 尝试在每个输入事件上执行此操作似乎并不能提供良好的用户体验 - 但如果您尝试提供输入掩码,那么您别无选择,只能更新输入事件的格式化值。如果您遇到问题,我可以更新示例代码
    猜你喜欢
    • 1970-01-01
    • 2018-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多