網站搜尋

typescript - Angular 5 模板驅動的十進位輸入


我正在使用 Angular 5 的模板驅動表單,並且在表單中有幾個數字輸入欄位。

我的需求非常簡單,我感到驚訝的是我找不到解決方法

基本上,每個數字輸入應顯示為帶有千位分隔符和可配置小數位數的十進制,但在模型中應以數字(不帶逗號)形式存儲該值。

我已經看過一些管道,但它們不適用,因為它們僅用於顯示,無法與雙向綁定一起使用。我也四處搜尋了許多關於指令的範例,希望它能通過暴露控制項的 NgModel 並操作其數據來實現,但也沒有任何結果。

我看過在 TypeScript 中使用單向綁定加 setter,但那樣很醜而且不可重用

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

你能指引我正確的方向嗎?我認為指令是可行的方式,但我找不到清楚的範例說明如何將輸入綁定與顯示分開,更重要的是,如果模型中已有資料,要如何在載入時顯示正確的值

提前感謝你!

答案#1

Jeto 給了我 90% 的解決方案,經過幾個調整後,我成功得到了我想要的精確行為

我遵循了這篇文章,達到了一個狀態,字段顯示正常,但它總是顯示截斷的值。我真正想要的是一個純粹的“遮罩”,這樣用戶可以輸入超過兩位小數的數值,但為了清晰起見,只會看到兩位小數,並且當滑鼠移上去時可以顯示完整的數字。

然後我使用這篇文章在指令中暴露 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 管道。你也可以傳入 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'"
 />