当前位置: 首页 > 知识库问答 >
问题:

格式化Angular 6指令中的数字/货币

濮阳宜
2023-03-14

我创建了一个货币指令,我将在每个需要货币格式的输入元素中使用它。

所以我有两个主机听众,一个是OnFocus,第二个是Blur

而且效果很好。但当我通过绑定设置输入值时,我需要格式化输入值

所以当我打开一个模态时,我得到了无格式的值...NgOnInit不起作用,因为它早期加注太多

这是我的指令代码。

import { Directive, HostListener, Input, OnInit, ElementRef, AfterViewInit, OnChanges, Renderer2, ViewChild } from '@angular/core';

import { CurrencyPipe, getCurrencySymbol } from '@angular/common';

import { NgControl, ControlValueAccessor } from '@angular/forms';

import { CustomCurrencyPipe } from '../pipes/custom-currency.pipe';

import { ModalDirective } from 'ngx-bootstrap/modal';



@Directive({

  selector: '[appCurencyFormat]',

  providers: [CustomCurrencyPipe]

})



export class CurrencyFormatDirective implements OnInit{

  //@Input('appNumberFormat') params: any;

  @Input() decimalNumber: number = 2;

  @Input() symbol: string = "symbol";

  //@Input() OnlyNumber: boolean;

  local: string;

  decimal: string;

  currency: string;

  element: any;



  @ViewChild(ModalDirective) childModal: ModalDirective;



  constructor(private elementRef: ElementRef, private ngControl: NgControl, private currencyPipe: CustomCurrencyPipe, private _renderer: Renderer2) {


    this.element = this.elementRef.nativeElement;    

  }



  @HostListener('keydown', ['$event']) onKeyDown(event) {

    let e = <KeyboardEvent>event;

    //190 in array for .

      if ([46, 8, 9, 27, 13, 110].indexOf(e.keyCode) !== -1 ||

        // Allow: Ctrl+A

        (e.keyCode === 65 && (e.ctrlKey || e.metaKey)) ||

        // Allow: Ctrl+C

        (e.keyCode === 67 && (e.ctrlKey || e.metaKey)) ||

        // Allow: Ctrl+V

        (e.keyCode === 86 && (e.ctrlKey || e.metaKey)) ||

        // Allow: Ctrl+X

        (e.keyCode === 88 && (e.ctrlKey || e.metaKey)) ||

        // Allow: home, end, left, right

        (e.keyCode >= 35 && e.keyCode <= 39)) {

        // let it happen, don't do anything

        return;

      }

      // Ensure that it is a number and stop the keypress

      if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {

        e.preventDefault();

      }    

  }  



  @HostListener('focus', ['$event.target.value'])

  onFocus(value: any) {

    this.ctrl.setValue(this.currencyPipe.convertToNumber(value));    

  }



  @HostListener('blur', ['$event.target.value'])

  onBlur(value: any) {

    this.ctrl.setValue(this.currencyPipe.transform(value, this.decimalNumber, this.symbol));

  }



  get ctrl() {    

    return this.ngControl.control;

  }

}

我的解决方案是在ngOnInit中设置一个时间间隔...

ngOnInit() {
        let m = window.setInterval(() => {
        console.log("Upao sam");
        console.log(this.ctrl.value);
        if (this.ctrl.value) {
          console.log(this.ctrl.value);
          if (seted) {
            window.clearInterval(m);
          } else {
            seted = true;
            this.ctrl.setValue(this.currencyPipe.transform(this.ctrl.value, this.decimalNumber, this.symbol));
          }
        }
      }, 500);
}

有没有人知道我可以使用哪个主机接收器,以尽量避免使用窗口.setInterval().或者,如果有人知道我该如何解决这个问题?

更新

ngOnChange()不是每次都引发的,所以选择的重复问题不能解决我的问题。

共有3个答案

萧英光
2023-03-14

< code>ngDoCheck()是一个有保证的生命周期挂钩,它将在每次角度触发变化检测时运行。

一个小的工作示例展示了当有变化时,指令的< code>ngDoCheck()钩子将总是被触发。

要了解为什么ngOnChange()不会一直引发以及为什么使用ngDoCheck()代替:

每当指令中的绑定 Input 属性发生更改时,它就会触发角度变化检测。角度如何检测输入是否更改?它比较简单更改对象表示输入的旧值和新值,如果它们之间存在差异,则角度触发ngOnChanges()生命周期挂钩。

因此,在某些情况下,您确实输入了某些内容,但比较的值没有更改(例如,您更改了通过突变和对象的属性进行输入,因此实际上简单更改的旧值和新值是相同的,因为Angular正在比较引用,而不是值),在这种情况下,它不会引发ngOnChange()钩子。

但是< code>ngDoChek()有所不同。我将使用关于< code>ngDoCheck()的一篇非常好的文章中的信息:

假设我们有以下组件/指令树:

Component A
    Component B
        Component C

因此,当角度运行变化检测时,操作顺序如下:

Checking A component:
  - update B input bindings
  - call NgDoCheck on the B component
  - update DOM interpolations for component A
 
 Checking B component:
    - update C input bindings
    - call NgDoCheck on the C component
    - update DOM interpolations for component B
 
   Checking C component:
      - update DOM interpolations for component C

正如您所看到的,每当有变更检测运行时,< code>ngDoCheck()总是被调用。除此之外,当组件/指令初始化时,它也会被调用(重置my blitzstack示例来查看)。所以:

在< code>ngDoCheck()中格式化输入值将解决您的问题

梁嘉澍
2023-03-14

您可以采取以下措施来解决此问题:

<input [ngModel]="item | customCurrencyPipe:'USD':'symbol':'2.2'" name="inputField" type="text" 
(ngModelChange)="item = $event||0.00" [ngModelOptions]="{updateOn:'blur'}"/>

1) 将绑定拆分为单向绑定和事件绑定。

2)用事件绑定“ngModelChange”用提供的输入恢复值。

3)在“模糊”上更新值,因此任何不是数字的文本都不能提供 // 根据需要可选

4)自定义货币管道:这将具有货币管道的默认功能,但如果没有提供数字,则不会升级,而是会返回默认值或不允许数字以外的其他功能//根据要求

通过上述步骤,您将能够以更少的黑客和有希望的解决方案实现预期的结果。

冷正信
2023-03-14

我会使用整个值访问器。这是我所有输入的内容。你可以这样写

@Component({
  selector: 'ks-input',
  template: `<input [(ngModel)]="value" />`,
  styleUrls: ['./whatever.component.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => InputComponent),
      multi: true
    }
  ]
})

export class InputComponent implements ControlValueAccessor {

  @Input('value') _value = '';
  onChange: any = () => {
  };
  onTouched: any = () => {
  };

  get value() {
    return this._value;
  }

  set value(val) {
    this._value = val;
    this.onChange(val);
    this.onTouched();
  }

  registerOnChange(fn) {
    this.onChange = fn;
  }

  registerOnTouched(fn) {
    this.onTouched = fn;
  }

  writeValue(value) {
    this.value = value;
  }
}
 类似资料:
  • 在我当前的项目中,我将货币值存储为表示美分数的。但是,当用户在文本字段中输入此值时,他们很可能希望将其输入为十进制值。此外,如果用户不手动输入,我想在前面加上一个美元符号。我如何利用为我完成大部分工作?或者是否有其他解决方案使用预先存在的Swing组件,这样我就不必通过手动编码来重新发明轮子?

  • 问题内容: 我想用JavaScript格式化价格。我想要一个以a 作为参数并返回如下格式的函数: 最好的方法是什么? 问题答案: 好的,根据您的发言,我正在使用此功能: 我乐于接受改进建议(我不愿意仅仅为了做到这一点就不包括YUI :))我已经知道我应该检测到“”。而不只是将其用作小数点分隔符…

  • 我有一个带有一些数值的字符串。 然而,这两者都给出了错误。 实现这种格式的正确途径是什么? 这是jasper report jrxml的一部分,我希望在这里避免报告上出现“null”,从而插入以下代码: 如何解决这一问题? 多谢阅读。

  • 问题内容: 我正在使用我给定的语言环境获取自定义货币格式。但是,这始终包含我不需要的货币符号,我只想要给定语言环境的正确货币数字格式而没有货币符号。 做一个抛出一个异常.. 问题答案: 以下作品。这有点丑陋,但可以履行合同: 您还可以从货币格式中获取模式,删除货币符号,然后从新模式中重构新格式:

  • 所有-我有一个,它将格式化为货币格式: 这很好,问题是我的编辑文本只需要整数,所以我不允许用户输入美分。因此,我想要1比12比123比1234,而不是0.01比0.12比1.23比12.34。如何去掉小数点,但保留逗号?非常感谢。

  • 问题内容: 我想知道如何使用angularjs指令在输入字段中自动设置数字格式?在输入字段中输入6042919283时,我希望它显示为604-291-9283。 谢谢 问题答案: 您可以使用UI Utils遮罩。 它允许您定义允许的输入格式,并将为您处理验证以及格式设置