如何使用Angular 4与Ionic 3中的ngModel分别设置输入值

时间:2017-08-28 19:04:51

标签: angular ionic3

我有一个指令我正在为离子3应用中的货币输入创建。我基本上想要的是一个输入,表示$ 11.11,但将ngModel值设置为11.11。

我的模型值设置正确,格式化的字符串值正确,但我无法获取输入以显示格式化的值。实际上,我的输入显示我输入的任何内容,字母和标点符号,但所有记录的值都是正确的。有谁知道我错过了什么或更好的方式来实现我想要实现的目标?

示例
输入的文字输入:1111
ngModel值:11.11
console.log输入值:$ 11.11
实际输入值:1111(应为11.11美元)

import {Directive, Attribute, Output, EventEmitter, ElementRef, Renderer2} from '@angular/core';
import { NgModel } from '@angular/forms';
import {CurrencyPipe} from "@angular/common";

/**
 * Generated class for the CurrencyInputDirective directive.
 *
 * See https://angular.io/docs/ts/latest/api/core/index/DirectiveMetadata-class.html
 * for more info on Angular Directives.
 */
@Directive({
  selector: '[currency-input]',
  providers: [NgModel]
})
export class CurrencyInputDirective {

  maximumAmount: number;
  currencyCode: string;
  decimals: number;
  modelValue: number;

  @Output() ciExceededMax: EventEmitter<any> = new EventEmitter();

  constructor(public model: NgModel,
              public elementRef: ElementRef,
              private currencyPipe: CurrencyPipe,
              private renderer: Renderer2,
              @Attribute("ci-maximum-amount") maximumAmount: number,
              @Attribute("ci-currency-code") currencyCode: string,
              @Attribute("ci-decimals") decimals: number) {

    this.maximumAmount = (maximumAmount) ? maximumAmount : 10000;
    this.currencyCode = (currencyCode) ? currencyCode: 'USD';
    this.decimals = (decimals) ? Math.trunc(decimals) : 2;

    let directive = this;
    this.model.valueChanges.subscribe(function (value) {
      directive.modelValue = directive.getModelValue(value);
      directive.model.viewToModelUpdate(directive.modelValue);
      directive.writeValueToInput(directive.getFormattedModelValue(directive.modelValue));
    });

  }

  writeValueToInput(value) {

    //this.elementRef.nativeElement.value = value;
    this.renderer.setProperty(this.elementRef.nativeElement, 'value', value);

    console.log("element ref value " + this.elementRef.nativeElement.value);
    console.log("element ref " + JSON.stringify(this.elementRef.nativeElement, undefined, 2));
  }

  getFormattedModelValue(value) {
    let currencyDecimals = '1.' + this.decimals + "-" + this.decimals;

    let retVal: string = (!value) ? null : this.currencyPipe.transform(value, this.currencyCode, true, currencyDecimals);
    return (retVal) ? retVal : this.currencyPipe.transform(0, this.currencyCode, true, currencyDecimals);
  }

  getModelValue(value) {

    if(!value)
      return 0;

    let strippedValue: string = value.replace(/[^0-9]/g,"");
    let parsedInt: number = parseInt(strippedValue);
    let calculatedAmount = (parsedInt / Math.pow(10, this.decimals));

    if(calculatedAmount > this.maximumAmount){
      calculatedAmount = this.modelValue;

      setTimeout( () => {
        this.ciExceededMax.emit({amount: calculatedAmount, maxAmount: this.maximumAmount});
      }, 1);
    }

    console.log("returning calculated amount " + calculatedAmount);

    return calculatedAmount;
  }

}

1 个答案:

答案 0 :(得分:0)

我明白了。我需要使用NgControl来写入输入值。

import {Directive, Attribute, Output, EventEmitter} from '@angular/core';
import {NgModel, NgControl} from '@angular/forms';
import {CurrencyPipe} from "@angular/common";

/**
 * Generated class for the CurrencyInputDirective directive.
 *
 * See https://angular.io/docs/ts/latest/api/core/index/DirectiveMetadata-class.html
 * for more info on Angular Directives.
 */
@Directive({
  selector: '[currency-input]',
  providers: [NgModel]
})
export class CurrencyInputDirective {

  maximumAmount: number;
  currencyCode: string;
  decimals: number;
  modelValue: number;

  @Output() ciExceededMax: EventEmitter<any> = new EventEmitter();

  constructor(public model: NgModel,
              private control : NgControl,
              private currencyPipe: CurrencyPipe,
              @Attribute("ci-maximum-amount") maximumAmount: number,
              @Attribute("ci-currency-code") currencyCode: string,
              @Attribute("ci-decimals") decimals: number) {

    this.maximumAmount = (maximumAmount) ? maximumAmount : 10000;
    this.currencyCode = (currencyCode) ? currencyCode: 'USD';
    this.decimals = (decimals) ? Math.trunc(decimals) : 2;

    let directive = this;
    this.model.valueChanges.subscribe(function (value) {
      directive.modelValue = directive.getModelValue(value);
      directive.model.viewToModelUpdate(directive.modelValue);
      directive.control.valueAccessor.writeValue(directive.getFormattedModelValue(directive.modelValue));
    });

  }

  getFormattedModelValue(value) {
    let currencyDecimals = '1.' + this.decimals + "-" + this.decimals;

    let retVal: string = (!value) ? null : this.currencyPipe.transform(value, this.currencyCode, true, currencyDecimals);
    return (retVal) ? retVal : this.currencyPipe.transform(0, this.currencyCode, true, currencyDecimals);
  }

  getModelValue(value) {

    if(!value)
      return 0;

    let strippedValue: string = value.replace(/[^0-9]/g,"");
    let parsedInt: number = parseInt(strippedValue);
    let calculatedAmount = (parsedInt / Math.pow(10, this.decimals));

    if(calculatedAmount > this.maximumAmount){
      calculatedAmount = this.modelValue;

      setTimeout( () => {
        this.ciExceededMax.emit({amount: calculatedAmount, maxAmount: this.maximumAmount});
      }, 1);
    }

    return calculatedAmount;
  }

}