udos86 / ng-dynamic-forms

Rapid form development library for Angular
ISC License
1.32k stars 368 forks source link

[MaskedInput] Text-Mask value pushed to custom validator too quickly #870

Open maroy1986 opened 5 years ago

maroy1986 commented 5 years ago

I'm submitting a


[x] Bug / Regression (maybe?)
[ ] Feature Request / Proposal
[x] Question (more likely)

I'm using


NG Dynamic Forms Version: `6.2.0`

[ ] Basic UI
[ ] Bootstrap UI  
[ ] Foundation UI
[ ] Ionic UI
[ ] Kendo UI
[x] Material  
[ ] NG Bootstrap
[ ] Prime NG

Description

Hi there!

I'm having an issue while using a mask input combined with a validator. The issue is, the validator received the value too fast onChange. Here's more context.

I have set a mask on a field to allow the user to enter an SSN value which should be formatted like this: 000-00-0000. Up to this, everything is fine, the mask displays correctly and the user doesn't need to care about the format. All fine, until we want to hook a custom validator on it.

So, I made a ssnValidator function that gets triggered, onBlur and on form submit (we call the validation on submit) to ensure the user enters the proper value. Here it is:

export function ssnValidator(control: AbstractControl): ValidationErrors | null {
  if (!control.value) { return null; }
  let value = (control.value as string);

  if (!value.replace(/_|-/g, '')) {
    return null;
  }

  // Validate SSN against regexp
  const isEnteredSsnValid = /^\d{3}-\d{2}-\d{4}$/.test(value);
  return value.length !== 11 || !isEnteredSsnValid ? { ssnValidator: true } : null;
}

Another problem arise from there also. The value that is received in the validator includes the placeholder. So let's say the user typed 1, the value received by the validation will be 1____-__-____ as you can see here : image

The value received should be 1__-__-____ (and this is the actual value that gets displayed at the end) but looks like text-mask hasn't finish his own business underneath before the value gets sent to the validator. So I need to strip the placeholder to actually know if the user entered something or not, otherwise I only get a bunch of placeholders. Same thing goes if the user change a value in the middle of the mask, I end up receiving something like this 123-123-123_ but the UI display 123-12-3123 which is what I was expecting.

Back to the initial issue, I'm not sure this is an issue on your end at the end, probably more a text-mask issue since you only use the directive in your code. I've tried going the async validator way by using an Observable on which I pipe a debounceTime but that doesn't work either, value received is still wrong and doesn't fire up again once the value in the field get ajusted by text-mask.

Have you ever heard of this or am I the first to report this? I've found another issue quite similar to mine, which is #745 but they doesn't seems to be using any mask.

This issue kindda makes the usage of text-mask useless as soon as you start doing some custom validation. What's your toughts @udos86 ?

Thanks!

udos86 commented 5 years ago

@maroy1986

Thank you for giving insight on this topic. It's a difficult one. As you pointed out I'm basically just making using of the text mask directive.

Without having the time right now to dive deeper into this, but did you consider controlling this via updateOn?