如何在angular2中动态格式化输入元素?

时间:2016-07-16 19:03:19

标签: angular angular2-forms

我正在使用angular2,新形式的api。

我想要一个电话号码输入框,它会在用户输入时自动格式化。

例如用户输入:

12345678901

当他们输入可识别的电话号码时,它会变为

1 (234) 567-8901

我想出了如何在输入控件上添加指令,但我不知道如何将自己注入输入处理管道。

2 个答案:

答案 0 :(得分:9)

您必须创建自己的指令,以此为例,它使用Phone.format进行转换,将原始数字存储在模型中,但将格式化的数字显示给用户:

import { Directive } from '@angular/core'
import { NgControl } from '@angular/forms'
import { Phone } from '../phone'

@Directive({
  selector: '[ngModel][phone]',
  host: {
    '(ngModelChange)': 'onInputChange($event)',
    '(blur)': 'onBlur($event)'
  }
})
export class PhoneDirective {

  constructor (control: NgControl) {
    this.control = control
  }

  ngOnInit () {
    let formatted = Phone.format(this.control.model)
    setTimeout(() => this.control.valueAccessor.writeValue(formatted), 0)
  }

  onBlur () {
    let val = this.control.model
    let raw = val.replace(/\W/g, '')
    let formatted = Phone.format(raw)

    this.control.valueAccessor.writeValue(formatted)
    this.control.viewToModelUpdate(raw)
  }

  onInputChange (val) {
    let raw = val.replace(/\W/g, '')
    if (val !== raw) this.control.viewToModelUpdate(raw)
  }
}

答案 1 :(得分:0)

下面的指令将在您键入时格式化该值:

  1. 当用户输入值时,input方法被触发(视图->模型,在AngularJS中又称为$ parser)。它可以确保视图获得格式化视图(通过render方法),而模型则获得原始数值(通过propagateChange方法)。
  2. 更新模型时会触发writeValue方法(模型->视图,即AngularJS中的$ formatter)。这样可以确保视图获得格式化视图(通过render方法)。
  3. format方法包含格式化视图的逻辑。我们在那里需要一些额外的条件,以确保用户不仅可以输入字符,还可以将它们一个接一个地删除。

要使用指令,请将其注册到模块中并将其链接到输入,例如:

<input appFormattedNumber formControlName= .../>

(我只用反应形式进行了测试)

import {Directive, ElementRef, forwardRef, HostListener, Renderer2} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';

@Directive({
  selector: '[appFormattedNumber]',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => FormattedNumberDirective),
      multi: true
    }
  ]
})
export class FormattedNumberDirective implements ControlValueAccessor {
  propagateChange;

  constructor( private renderer: Renderer2, private element: ElementRef ) {}

  @HostListener('input', [ '$event.target.value' ])
  input( value ) {
    const canonical = this.removeNonNumericCharacters(value);

    const formatted = this.format(canonical);
    this.render(formatted);

    this.propagateChange(canonical);
  }
  writeValue( value: any ): void {
    const canonical = this.removeNonNumericCharacters(value.toString());
    const formatted = this.format(canonical);
    this.render(formatted);
  }

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

  registerOnTouched(fn: any): void {}

  setDisabledState(isDisabled: boolean): void {}

  private removeNonNumericCharacters(value): string {
    return value.replace(/\D/g, '');
  }

  private format(value): string {
    if (value.length < 5) {
      return value;
    }

    const int = value.substring(0, 1);
    const areaCode = value.substring(1, 4);
    const ext1 = value.substring(4, 7);
    const ext2 = value.substring(7, 11);
    const ext = ext2 ? ` ${ext1}-${ext2}` : `${ext1}`;

    return `${int} (${areaCode}) ${ext}`;
  }

  private render(value) {
    const element = this.element.nativeElement;
    this.renderer.setProperty(element, 'value', value);
  }
}