Как получить сумму, преобразованную в значение денежного канала после получения сообщения об ошибке в angular8 - PullRequest
5 голосов
/ 07 марта 2020

Я использую валютную трубу в событии размытия. Но это работает нормально в первый раз, когда я получаю сообщение об ошибке проверки, если я удаляю несколько чисел и получаю сообщение, оно не будет отформатировано, чтобы формат валюты остался в том формате, который удалил пользователь. Например, я дал это число: 36543265, поэтому, когда я вышел из ввода, он был отформатирован в $36,543,265.00 с сообщением об ошибке проверки. Поэтому, если я удаляю 265.00 из $36,543,265.00, у меня все еще есть сообщение об ошибке проверки. таким образом, сообщение об ошибке проверки исчезло и осталось с этим форматом $36,543, но оно не пришло в правильный формат. Как мне сделать это в правильном формате денежного канала USD, после очистки сообщения проверки.

Как я могу сделать его правильно отформатированным на основе удаления значений пользователем.

TS :

public transformAmount(element, name) {
  if (name == "amount") {
    let formattedAmount = this.currencyPipe.transform(this.eoInfoForm.value.amount, 'USD');
    element.target.value = formattedAmount;
    this.eoInfoForm.get('amount').setValue(formattedAmount);
    if (this.eoInfoForm.get('amount').status === 'VALID') {
      this.amt = false; 
    } 
    else {
      this.amt = true;
    } 
  } 
}

HTML:

 <input type="text" class="form-control" placeholder="Amount in dolars"
                    formControlName="amount" autocomplete="off" maxlength="8" allowNumberOnly (blur)="transformAmount($event,'amount')" [ngClass]="{ 'is-invalid': amt  && eoInfo.amount.invalid }">
                    <div *ngIf="amt && eoInfo.amount.invalid" class="invalid-feedback">
                        <div *ngIf="amt && eoInfo.amount.invalid">Maximum of 8 characters including $ is allowed</div>
                      </div>

DEMO: DEMO

Ответы [ 4 ]

1 голос
/ 18 марта 2020

вы можете написать несколько простую директиву, чтобы сделать это:

import { Directive, HostListener, ElementRef, OnInit, Input } from "@angular/core";
import { CurrencyPipe } from '@angular/common';

@Directive({ selector: "[currencyInput]" })
export class CurrencyInputDirective implements OnInit {

  // build the regex based on max pre decimal digits allowed
  private regexString(max?: number) {
    const maxStr = max ? `{0,${max}}` : `+`;
    return `^(\\d${maxStr}(\\.\\d{0,2})?|\\.\\d{0,2})$`
  }
  private digitRegex: RegExp;
  private setRegex(maxDigits?: number) {
    this.digitRegex = new RegExp(this.regexString(maxDigits), 'g')
  }
  @Input()
  set maxDigits(maxDigits: number) {
    this.setRegex(maxDigits);
  } 

  private el: HTMLInputElement;

  constructor(
    private elementRef: ElementRef,
    private currencyPipe: CurrencyPipe
  ) {
    this.el = this.elementRef.nativeElement;
    this.setRegex();
  }

  ngOnInit() {
    this.el.value = this.currencyPipe.transform(this.el.value, 'USD');
  }

  @HostListener("focus", ["$event.target.value"])
  onFocus(value) {
    // on focus remove currency formatting
    this.el.value = value.replace(/[^0-9.]+/g, '')
  }

  @HostListener("blur", ["$event.target.value"])
  onBlur(value) {
    // on blur, add currency formatting
    this.el.value = this.currencyPipe.transform(value, 'USD');
  }

  // variable to store last valid input
  private lastValid = '';
  @HostListener('input', ['$event'])
  onInput(event) {
    // on input, run regex to only allow certain characters and format
    const cleanValue = (event.target.value.match(this.digitRegex) || []).join('')
    if (cleanValue || !event.target.value)
      this.lastValid = cleanValue
    this.el.value = cleanValue || this.lastValid
  }
}

директива преобразует значение в число в фокусе и обратно в форматированную строку валюты при размытии.

use как:

<input type="text" class="form-control" placeholder="Amount in dolars" autocomplete="off"
  formControlName="amount" currencyInput maxDigits="9" 
  [ngClass]="{ 'is-invalid': eoInfo.amount.dirty  && eoInfo.amount.invalid }">

блиц: https://stackblitz.com/edit/angular-csyslb?file=src%2Fapp%2Fcurrency-input.directive.ts

0 голосов
/ 20 марта 2020

Первое, на что я хочу указать:

Вы используете maxlength="8", что нормально, пока вы не начнете использовать валютную трубу. Символы, добавленные вашей валютной трубкой, будут приняты во внимание. Я не знаю, является ли это требуемым поведением, но оно определенно не интуитивно с точки зрения пользователя.

«Я вижу ограничение в 8 символов, я могу ввести до 8 символов» - это первое, о чем я подумаю при чтении сообщения проверки. Я не хочу думать о форматировании валюты самостоятельно, пока я ввожу свое (в то время) неформатированное число.

Я бы сказал, что либо получим maxLength 14 (8 + 1 доллар) знак + 2 запятых + 1 точка + двойные цифры - максимально возможное число для USD = 14 символов) и оставьте сообщение проверки в качестве значения как 8. Или, если вы действительно хотите только 8 символов после форматирования, установите значение сообщения проверки как 3 ( 3 + 1 знак доллара + 1 запятая + 1 точка + двойные цифры = 7) после форматирования 4 цифры переходят к 9 символам, потому что добавляется дополнительная ди git + запятая, идущая к 9 символам, что больше maxLength 8 .

Вы также можете использовать пользовательскую проверку длины и правильно проверить себя (что хорошо, если формат валюты может отличаться) вместо того, чтобы полагаться на универсальный c *ngIf="amt && eoInfo.amount.invalid"


Теперь для вашей актуальной проблемы, решение, которое я думаю, было бы неплохо, это удалить форматирование во время редактирования. Для пользователя никогда не бывает практичным редактировать, и ему приходится перемещаться по . , и $, когда все, что их волнует при редактировании, это действительно цифры. Вы можете создать «обратную валютную трубу», когда пользователь фокусирует поле так, что все, что он видит, это число.

Я сделал быструю форк из вашей Stackblitz demo с предположением, что макс. длина относится к числу цифр перед десятичной точкой.

Дайте мне знать, если что-то нужно изменить, и поможет ли это вообще решить вашу проблему.

0 голосов
/ 18 марта 2020

Я изменил некоторые вещи в вашем коде, чтобы он работал: Рабочее решение

Вот основная часть:

public transformAmount(name) {
    let formattedAmount = this.currencyPipe.transform(
        this.eoInfoForm.value.amount.replace(/[^\d.E+]/gm, ""),
        "USD"
    );
    this.eoInfoForm.get(name).setValue(formattedAmount);
}

Что я did инвертирует преобразование канала в значение перед тем, как передать его в канал. Я использовал регулярное выражение /[^\d.E+]/gm, чтобы удалить все, что не включено в:

  • Число
  • Символ точки
  • Символ "E"
  • "+" символ

"E" и "+" предназначены для обработки конкретного c случая, когда число очень большое и отображается как $1.00E+37.

Я предположил, что максимальная длина 8 применима, когда текст был отформатирован, поэтому я не трогал его (в противном случае вам нужен пользовательский валидатор). Я просто переместил его в файл TypeScript, поскольку вы используете реактивные формы, поэтому лучше не смешивать понятия шаблонных форм.

0 голосов
/ 07 марта 2020

После ввода знака $ enter image description here

у вас есть ошибка с вашим кодом. Вы можете использовать это регулярное выражение, чтобы брать только цифры из текста

var thenum = thestring.replace( /^\D+/g, ''); // replace all leading non-digits with nothing

или просто проверьте, что первый символ, и если это $, удалите его

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...