自定义值访问器-并非每次都更新模型

时间:2019-03-30 22:31:25

标签: angular

我有货币指令。我显示了简单的表格和总和。问题是,总和字段仅在我离开input(lostfocus)时才更新。 当我删除以下行:提供程序:[CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]可以,但是我需要它,因为我想在输入中显示“,”,但在模型中应该显示“。”。我还尝试添加用于keyup的相同代码,以用于模糊和求和,但是在用户未完成键入时将其值格式化为

代码:https://stackblitz.com/edit/angular-1qzpaz?embed=1&file=src/app/app.component.html

指令:

import {AfterViewInit, Directive, ElementRef, forwardRef, HostListener, Input, Renderer2} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
import {CurrencyMaskService} from "./currency-mask.service";

const noop = () => {
};

export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => CurrencyMaskDirective),
  multi: true
};

@Directive({
  selector: '[appCurrencyMask]',
  providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class CurrencyMaskDirective implements AfterViewInit, ControlValueAccessor {
  private el: HTMLInputElement;
  private innerValue: any;
  @Input('allowNegative')
  allowNegative: boolean;   // Optional Parameter to allow for negative number interaction

  @Input('fractionSize')
  fractionSize: number;

  constructor(private elementRef: ElementRef, private currencyMaskService: CurrencyMaskService, private renderer: Renderer2) {
    this.el = elementRef.nativeElement;
  }

  // Placeholders for the callbacks which are later providesd
  // by the Control Value Accessor
  private onTouchedCallback: () => void = noop;
  private onChangeCallback: (a: any) => void = noop;

  // set getter
  get value(): any {
    return this.innerValue;
  }

  // set accessor including call the onchange callback
  set value(v: any) {
    if (v !== this.innerValue) {
      this.innerValue = v;
      this.onChangeCallback(v);
    }
  }

  // From ControlValueAccessor interface
  writeValue(value: any) {
    if (value !== this.innerValue) {
      this.el.value = this.currencyMaskService.transform(value, this.allowNegative, this.fractionSize);
      if (value) {
        this.renderer.setAttribute(this.elementRef.nativeElement, 'value', value);
      }
      this.innerValue = value;
    }
  }

  // From ControlValueAccessor interface
  registerOnChange(fn: any) {
    this.onChangeCallback = fn;
  }

  // From ControlValueAccessor interface
  registerOnTouched(fn: any) {
    this.onTouchedCallback = fn;
  }

  ngAfterViewInit() {
    this.el.style.textAlign = 'right';
  }

  // On Focus remove all non-digit or decimal separator values
  @HostListener('focus', ['$event.target.value'])
  onfocus(value) {
    this.el.value = this.currencyMaskService.parse(value, this.allowNegative,  this.fractionSize);
  }

  // On Blue remove all symbols except last . and set to currency format
  @HostListener('blur', ['$event.target.value'])
  onBlur(value) {
    this.onTouchedCallback();
    this.el.value = this.currencyMaskService.transform(value, this.allowNegative,  this.fractionSize);
    this.innerValue = this.currencyMaskService.parse(this.el.value, this.allowNegative,  this.fractionSize);
    this.onChangeCallback(this.innerValue);
    if (this.innerValue) {
      this.renderer.setAttribute(this.elementRef.nativeElement, 'value', this.innerValue);
    }
  }

  // On Change remove all symbols except last . and set to currency format
  @HostListener('change', ['$event.target.value'])
  onChange(value) {
    this.el.value = this.currencyMaskService.transform(value, this.allowNegative,  this.fractionSize);
    this.innerValue = this.currencyMaskService.parse(this.el.value, this.allowNegative,  this.fractionSize);
    this.onChangeCallback(this.innerValue);
    if (this.innerValue) {
      this.renderer.setAttribute(this.elementRef.nativeElement, 'value', this.innerValue);
    }
  }

  // Prevent user to enter anything but digits and decimal separator
  @HostListener('keypress', ['$event'])
  onKeyPress(event) {
    //46 --> dot
    //44 --> comma
    const key = event.which || event.keyCode || 0;
    if (key === 45 && !this.allowNegative) {
      event.preventDefault();
    } else if (key === 45 && this.allowNegative) {
      // allow negative numbers
    } else if (key !== 44 && key > 31 && (key < 48 || key > 57)) {
      event.preventDefault();
    }
  }
}

0 个答案:

没有答案