Угловой 5 шаблон, управляемый десятичным вводом - PullRequest
0 голосов
/ 19 октября 2018

Я работаю с шаблонными формами Angular 5 и имею несколько числовых вводов в форме.

У меня очень простое требование, и я поражен тем, что не могу найти его решение

В основном каждый числовой ввод должен отображаться в виде десятичной дроби с тысячами разделителей и настраиваемымколичество знаков после запятой, но сохраните значение в виде числа (без запятых) в модели.

Я смотрел на каналы, которые неприменимы, так как они только отображают и не работают с двухсторонним связыванием. Я также искал высокие и низкие значения для примера директивы, которая делает это, выставляяNgModel элемента управления и манипулирует его данными, и никакой радости там тоже нет.

Я смотрел на одностороннюю привязку + установщик в TypeScript, но это уродливо и не может использоваться повторно

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

Можете ли вы указать мне правильное направление?Я думаю, что директива - это путь, но я не могу найти четкого примера того, как отделить входную привязку от отображения и, что важно, отобразить правильное значение при загрузке, если данные уже заполнены в модели

Заранее спасибо!

1 Ответ

0 голосов
/ 19 октября 2018

Джето дал мне 90% решения, и с помощью нескольких твиков мне удалось получить точное поведение, которое я вел после

Я следовал Эта статья и попал в состояние, когдаполе отображалось правильно, но оно всегда показывало усеченное значение.Что я действительно хотел, так это чистую «маску», чтобы пользователь мог выдавать более 2 дпс, но для ясности видел только 2 дпс и имел указатель мыши, чтобы показать весь рисунок.

Затем я использовал Эта статья , чтобы раскрыть NgModel в директиве, чтобы в фокусе вместо усеченного значения

отображалось необработанное значение ngModel.viewmodel.Моя директива теперь выглядит так (за исключением трубы для ясности. Это вырезка и вставка 1-й статьи на данный момент)

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, так что теперь это скорее оболочка для угловой трубы, которая работает с двухсторонней привязкой.Вы также можете передать стиль форматирования угловых чисел, например, 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'"
 />
...