【问题标题】:Angular 5 template driven Decimal inputAngular 5 模板驱动的十进制输入
【发布时间】:2018-10-19 10:37:58
【问题描述】:

我正在使用 Angular 5 模板驱动的表单,并且表单中有多个数字输入。

我的需求很简单,我很惊讶我找不到解决办法

基本上,每个数字输入应显示为带有千位分隔符和可配置小数位数的小数,但将值存储为模型上的数字(不带逗号)。

我查看了不适用的管道,因为它们仅用于显示并且不适用于双向绑定 我还在高处和低处搜索了一个指令示例,该指令通过公开控件的 NgModel 并操纵其数据来做到这一点,但那里也没有乐趣..

我已经看过 TypeScript 中的单向绑定 + 设置器,但这很丑陋且不可重用

<input type="number" [NgModel]="somevalue | number : '2.2-6'" (ngModelChange)="somevalue = formatNumber($event)"

你能指出我正确的方向吗? 我认为该指令是要走的路,但我找不到一个清晰的例子来说明如何将输入绑定与显示分开,重要的是如果模型中已经填充了数据,则在加载时显示正确的值

提前致谢!

【问题讨论】:

  • This article 可能会有所帮助。
  • 如果您只想在视图中显示逗号并保存不带逗号的数值,那么使用管道有什么问题?
  • stackoverflow.com/users/4899523/abdul-rafay Pipe 不适用于双向绑定,因此您必须像我在问题中显示的那样断开绑定。它很难看,并且您必须在每个需要使用十进制输入的组件中具有数据转换器功能。我正在寻找仅使用标记+指令(?)执行此操作的东西,而不会将组件与应编写一次的辅助内容弄乱
  • Jeto,这非常接近我的需要。唯一缺少的部分是,如果用户输入一个 3 dps 的值,它会截断模型上的值,这可能是一个有效的情况,他们只想看到 2dps 以清楚起见(我可能会有鼠标悬停显示没有截断的全部金额)我会再玩一些

标签: angular typescript angular5 angular6 directive


【解决方案1】:

Jeto 为我提供了 90% 的解决方案,并通过一些调整,设法获得了我所追求的确切行为

我关注This article 并进入该字段正确显示的状态,但它始终显示截断值。 我真正想要的是一个纯粹的“蒙版”,以便用户可以提供超过 2dps 的图像,但为了清晰起见,只能看到 2dps 并且鼠标悬停以显示整个图形。

然后我使用This article 在指令中公开 NgModel,以便在获得焦点时显示 ngModel.viewmodel 的原始值而不是截断值

我的指令现在看起来像这样(为了清楚起见,减去管道。它是目前第一篇文章的剪切和粘贴)

import { Directive, Input, HostListener, ElementRef, OnInit } from "@angular/core";
import { NgModel } from "@angular/forms";
import { DecimalPipe } from "./decimal-pipe";


    @Directive({
        selector: "[decimalFormatter][ngModel]",
        providers: [NgModel]
    })
    export class DecimalFormatterDirective implements OnInit {

        private el: HTMLInputElement;
        @Input('decimals') decimals: number;

        constructor(
            private elementRef: ElementRef,
            private decimalPipe: DecimalPipe,
            private ngModel: NgModel
        ) {
            this.el = this.elementRef.nativeElement;
        }

        ngOnInit() {

            if (this.decimals == null)
                this.decimals = 2;

            console.log(this.el);
            console.log(this.ngModel);

            this.el.value = this.decimalPipe.transform(this.el.value, this.decimals);
        }

        @HostListener("focus", ["$event.target.value"])
        onFocus(value) {
            console.log(this.el);
            console.log(this.ngModel);
            this.el.value = this.ngModel.viewModel; // opossite of transform
        }

        @HostListener("blur", ["$event.target.value"])
        onBlur(value) {
            console.log(this.el);
            console.log(this.ngModel);
            this.el.value = this.decimalPipe.transform(value, this.decimals);
        }

    }

编辑:小更新

我将它调用的管道从第一篇文章中的管道更改为 Angular 使用的实际数字管道,因此它现在更像是 Angular 管道的包装器,可用于双向绑定。 您还可以传入角度数字格式样式,例如 2.2-6

希望这可以帮助将来遇到同样问题的人!

指令:

import { Directive, Input, HostListener, ElementRef, OnInit } from "@angular/core";
import { NgModel } from "@angular/forms";
import { DecimalFormatPipe } from "./decimal-format-pipe";


    @Directive({
        selector: "[decimalFormatter][ngModel]",
        providers: [NgModel]
    })
    export class DecimalFormatterDirective implements OnInit {

        private el: HTMLInputElement;
        @Input('decimals') decimals: string;

        constructor(private elementRef: ElementRef,
            private ngModel: NgModel,
            private decimalFormatPipe: DecimalFormatPipe) {

            this.el = this.elementRef.nativeElement;

        }

        ngOnInit() {

            if (this.decimals == null)
                this.decimals = "2.0-6";


            console.log(this.el.value, this.decimals);
            this.el.value = this.decimalFormatPipe.transform(this.el.value, this.decimals);
        }

        @HostListener("focus", ["$event.target.value"])
        onFocus(value) {

            console.log(this.el.value, this.decimals);
            this.el.value = this.ngModel.viewModel; //Display the raw value on the model
        }

        @HostListener("blur", ["$event.target.value"])
        onBlur(value) {

            console.log(this.el.value, this.decimals);
            this.el.value = this.decimalFormatPipe.transform(this.el.value, this.decimals);
        }

    }

管道包装器

import { Pipe, PipeTransform, Inject, LOCALE_ID } from '@angular/core'
import { DecimalPipe } from '@angular/common';

@Pipe({ name: 'decimalFormatPipe' })
export class DecimalFormatPipe implements PipeTransform {

    constructor(@Inject(LOCALE_ID) private locale: string) {}

    transform(value: any, args: string) {
        let pipe = new DecimalPipe(this.locale);
        return pipe.transform(value, args);
    }
}

以及对输入的使用

<input #myNumberInputCtrl="ngModel"
       name="myNumberInput"
       spellcheck="false" 
       placeholder="Enter a Number.." 
       [(ngModel)]="myNumberModel" 
       required 
       decimalFormatter
       [decimals]="'0.0-6'"
 />

【讨论】:

  • 感谢实施。在我的情况下它非常有用。但是我有一个问题,在 ngOnInit 的值是“”,因此它没有被格式化。你也有这个问题吗?
猜你喜欢
  • 1970-01-01
  • 2018-08-15
  • 2019-04-08
  • 2017-01-29
  • 2017-03-31
  • 1970-01-01
  • 1970-01-01
  • 2017-05-17
  • 2022-01-27
相关资源
最近更新 更多