Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NumericValidator - differentiate errors for allowDecimal true/false #311

Closed
ChrisKaun opened this issue Apr 20, 2020 · 19 comments
Closed

NumericValidator - differentiate errors for allowDecimal true/false #311

ChrisKaun opened this issue Apr 20, 2020 · 19 comments

Comments

@ChrisKaun
Copy link

Describe the bug

Using a NumericValidator on two controls is an issue if one allows decimals and one forbids them, since the NumericValidator will set the error numeric to false if the value is invalid.

Assuming we create a FormGroup with a height and a age control:

    height: [
      '',
      RxwebValidators.numeric({
        acceptValue: NumericValueType.PositiveNumber,
        allowDecimal: true
      })
    ],
    age: [
      '',
      RxwebValidators.numeric({
        acceptValue: NumericValueType.PositiveNumber,
        allowDecimal: false
      })
    ]

And we translate the numeric error message as Must be a valid number this would make sense if the user enters any non-numeric values to the input.
But as soon as the user enters a decimal value to the age the control will get a translated error message Must be a valid number displayed.
Translating the error message to Can't be a decimal doesn't make sense since as soon as the user enters non-numeric values any of those controls it wouldn't match the input.

Expected Behavior

Differentiate the numeric error to a decimal and non decimal error.
If allowDecimal is true, change the key to numericDecimal, else leave it as numeric or rename it to numericInteger.

Other option would be to allow a custom message per Validation. There is a message parameter but it doesn't seem to have any impact on the error message.

    height: [
      '',
      RxwebValidators.numeric({
        acceptValue: NumericValueType.PositiveNumber,
        allowDecimal: true,
        message: 'mustBeADecimal' 
      })
    ],
    age: [
      '',
      RxwebValidators.numeric({
        acceptValue: NumericValueType.PositiveNumber,
        allowDecimal: false,
        message: 'mustBeAnInteger'
      })
    ]

Package Version

@rxweb/reactive-form-validators@1.9.8

Browser

Firefox 75.0

@ajayojha
Copy link
Member

@ChrisKaun Thanks for sharing the detailed information. The mentioned concern can be managed through messageKey property.
Here is an example:

 height: [
      '',
      RxwebValidators.numeric({
        acceptValue: NumericValueType.PositiveNumber,
        allowDecimal: true,
        messageKey: 'mustBeADecimal' 
      })
    ],
    age: [
      '',
      RxwebValidators.numeric({
        acceptValue: NumericValueType.PositiveNumber,
        allowDecimal: false,
        messageKey: 'mustBeAnInteger'
      })
    ]

As per the above code I replace the message property to messageKey. It's works as per your expectation. Please let me know, if there is any suggestion atop this.

@ChrisKaun
Copy link
Author

@ajayojha That sould work in my use case. The only thing that I would suggest is to mention that option in the docs.

@hoang-innomize
Copy link

@ajayojha I tried the numeric in the model using the decorator, but the format function is not working. Here is my model definition

export class WeightModel {
  @required()
  @numeric({
    acceptValue: NumericValueType.PositiveNumber,
    digitsInfo: '1.0-2',
    isFormat: true,
    allowDecimal: true,
  })
  @range({
    conditionalExpression: (x, y) => x.weightUom === WeightUOM.Kg,
    minimumNumber: 0,
    maximumNumber: 450,
  })
  @range({
    conditionalExpression: (x, y) => x.weightUom === WeightUOM.Lbs,
    minimumNumber: 0,
    maximumNumber: 1000,
  })
  weight: number;

  @prop({ defaultValue: WeightUOM.Kg })
  weightUom?: WeightUOM;
}

Do you know any reason why it does not work? I also tried with RxwebValidators.numeric({}) to define form but it also does not work.

I am using the latest angular version

@ajayojha
Copy link
Member

@hoang-innomizetech Please share the stackblitz example.

@hoang-innomize
Copy link

hoang-innomize commented Apr 21, 2020

@ajayojha I just fixed this issue by importing the RxReactiveFormsModule into my app. Previously, I only wanted to configure the RxFormBuilder provider to avoid import that module

@ajayojha
Copy link
Member

ajayojha commented Apr 21, 2020 via email

@ChrisKaun
Copy link
Author

@ajayojha Just tested the messageKey option. The error still gets applied to the default numeric key.

@ajayojha
Copy link
Member

@ChrisKaun Please refer to the stackblitz example. It's working as expected. The key property won't change but the error message will be changed based upon the provided messageKey.

Testing Steps:

  1. Enter Value a value in both of the textbox.
  2. See the error JSON.

Please highlight if something is incorrect.

@ChrisKaun
Copy link
Author

Okay this works, didn't know that I need to register the validation messages.

This won't work for my usecase since I need to change the error key, not the message itself. The key is used in a hash to lookup the translation for the current locale.

@ajayojha
Copy link
Member

ajayojha commented Apr 21, 2020 via email

@ChrisKaun
Copy link
Author

Which translation package you are using?

In this case none. I simply use the key in a hash object to lookup the translation.

export const LocaleData: any = {
  de: {
    mustBeInt: () => 'Muss eine Ganzzahl sein',
    mustBeFloat: () => 'Muss eine Dezimalzahl sein'
  },
  en: {
    mustBeInt: () => 'Must be a integer',
    mustBeFloat: () => 'Must be a decimal'
  }
}

can you share code snippet?

Just a basic fork of your stackblitz.
https://stackblitz.com/edit/rxweb-numeric-message-key-example-snp1ld?file=src%2Fapp%2Fnumeric-message-key.component.html

Added a weight control that uses a custom numeric validator. The error message key is added dependent on the used method. Then I can use the key for translation lookup.

Same logic would work with your messageKey option, but then I would need to translate all messages, instead of the keys.

@ajayojha
Copy link
Member

@ChrisKaun I try to accommodate multilingual error messages as per your case with the lib. Please refer to the stackblitz example: https://stackblitz.com/edit/rxweb-numeric-message-key-example?file=src%2Fapp%2Fapp.component.ts

@hoang-innomize
Copy link

hoang-innomize commented Apr 22, 2020

@ajayojha

Thanks for the update, I thought you have imported the module and still you are facing the issue. Anyways it’s good to know that numeric format is working as expected.

The numeric format is working but it doesn't solve my problem. Since our application needs to support multilingual, so we have to find a way to specific locale when formatting instead of using default LOCALE_ID. I read the code and cannot find out any way to do that.

I have created this stackblitz and registered some locales, but it seems does not work non-default locale (i.e. de)

Do you have any ideas to make this works?

@ajayojha
Copy link
Member

@hoang-innomizetech I will check and let you know in two hours, As I am in between something to releasing translation package.

@hoang-innomize
Copy link

@ajayojha We are using ngx-translate library for translation. We need the messageKey value passed to the error object along with the message prop so that we don't have to map the message and key again. Is this possible?

@ajayojha
Copy link
Member

@hoang-innomizetech I am implementing the feature for multilingual messaging with our translation package and that works with other translation packages as well, I hope so :).

It would be great if you share a small code snippet of form control error message with ngx-translate. Because this is helpful for me to cover your project case as well, If I missed something.

@ajayojha
Copy link
Member

ajayojha commented Apr 22, 2020

@ajayojha

Thanks for the update, I thought you have imported the module and still you are facing the issue. Anyways it’s good to know that numeric format is working as expected.

The numeric format is working but it doesn't solve my problem. Since our application needs to support multilingual, so we have to find a way to specific locale when formatting instead of using default LOCALE_ID. I read the code and cannot find out any way to do that.

I have created this stackblitz and registered some locales, but it seems does not work non-default locale (i.e. de)

Do you have any ideas to make this works?

@hoang-innomizetech I reviewed the provided example, As such, there is no feature available that works with multiple locales.

I am thinking to resolve the decimal separator and group separator on demand, which can be configured on ReactiveFormConfig level as well as numeric validator level.

What do you think, will it be helpful for your project?

Feel free to share your inputs :).

@hoang-innomize
Copy link

I read the code and noticed that we can configure the number globally using ReactiveFormConfig but it seems not to work. Is this seem an issue?

ReactiveFormConfig.set({
      validationMessage: { numeric: "Please enter valid number" },
      // defaultValidationLocale: {
      //   alpha: ValidationAlphabetLocale.danish,
      //   alphaNumeric: ValidationAlphabetLocale.danish,
      // },
      // allowDecimalSymbol: ",",
      number: {
        decimalSymbol: ',',
        groupSymbol: '.',
      }
    });

And if we configure the ReactiveFormConfig on demand, we might have an issue with the formatted value, it will not reformat without refresh the page.

@ajayojha
Copy link
Member

I am closing this ticket as no further action required on this :).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants