Open ACmaster7 opened 1 month ago
Hello?? I think this is a major issue here and I haven't been able to solve it.
There are multiple ways of adding validation to forms in react-aria and they need to be able to be used together.
I customize the native HTML constraint error messages by passing the errorMessage prop like this:
errorMessage={({ validationDetails }) => validationDetails.valueMissing ? 'Enter a phone number!' : ''}
I also need complex pattern validation for phone numbers across multiple countries, using the validate prop:
validate={value => isValidPhoneNumber(value) ? null : 'Please enter a correct phone number'}
Additionally, on form submission, the server checks if the phone number exists in the database. If not, the server returns an error saying the phone number doesn’t exist. I need to display this server validation error using the validationErrors prop:
<Form
validationErrors={{ phonenumber: serverErrorForPhonenumber }}
onSubmit={onSubmit}
>
The problem is: because I’m customizing the native HTML constraint error messages (as shown in your docs), the FieldError component only shows either "Enter a phone number" or nothing (due to the empty string in the ternary operator).
This prevents any error messages from the server or custom validation logic from being displayed in the FieldError component. Essentially, once I customize the HTML constraint message, all other error messages (whether from the validate prop or validationErrors) are not displayed!
I have already provided a codesandbox example of this issue in my previous message. Thanks
The original validationErrors
are also passed to the FieldError component. Could you do something like this?
<FieldError>
{({ validationDetails, validationErrors }) => validationDetails.valueMissing ? 'Please enter a username' : validationErrors.join(' ')}
</FieldError>
Thank you this works! Since I’m using the reusable wrapper for the TextField component from the docs here, I’m passing the errorMessage prop to MyTextField like this:
<Form
validationErrors={{username: testServerError}}
>
<MyTextField
type="text"
isRequired={true}
errorMessage={({ validationDetails, validationErrors }) =>
validationDetails.valueMissing ? 'Please enter a username' : validationErrors.join(' ')}
validate={value => isValidPattern(value) ? null : 'Please match the required pattern!'}
label='Username'
name="username"
>
</Form>
While this solution works, it feels more like a workaround. Handling this automatically seems like something the library should manage.
Would you consider looking into this further, or do you feel this is the intended approach?
No this is intended. I don't think we can assume that an empty string means you want to show the default. It might mean you don't want to show that error. This gives you full control. Perhaps we could update the example in the docs though.
No this is intended. I don't think we can assume that an empty string means you want to show the default. It might mean you don't want to show that error. This gives you full control.
I see your point, but I believe it would be helpful to allow customization of native HTML constraint validation messages separately for each form field, without interfering with the default error handling. Just a suggestion.
Perhaps we could update the example in the docs though.
Yes, the docs could definitely use an update to help clarify this distinction for others as well 😀👌
Well, I thought the issue was resolved by following your solution, but after further testing, I’ve encountered another problem.
It seems that when the validate prop doesn't return null, it completely disables the native HTML constraint errors! This forces me to write the logic for native constraints, like empty values, inside the validate prop myself.
I first tested your solution with an additional validate prop like this:
validate={value => value === 'admin' ? 'Nice Try!' : null}
It worked as expected—if the value was 'admin', the field became invalid, and returning null still allowed the valueMissing constraint to trigger.
Then I implemented my actual validation logic:
validate={value => !isValidEmailOrPhone(value) ? 'Enter a **valid** email or phone number' : null}
Here’s the full component setup:
<MyTextField
type="text"
isRequired={true}
errorMessage={({ validationDetails, validationErrors }) =>
validationDetails.valueMissing ? 'Mobile or Email is required!' : validationErrors.join('')}
validate={value => !isValidEmailOrMobile(value) ? 'Enter a **valid** email or mobile number' : null}
label='Email or Mobile'
name="username"
/>
the validate prop will only return null when the value is actually a valid email or mobile number, so in any other case such as an empty value it will still return the string: "Enter a valid email or mobile number". (It shows the "Enter a valid email or mobile number" message even when the field is empty. When I submit the form with an empty field, it should trigger the valueMissing error and return 'Mobile or Email is required!'.)
The whole problem is that I need to customize and have the native HTML constraint error messages (like for isRequired, minLength, etc.) while also being able to display errors for more complex validation logic.
It seems like we can't fully combine these different types of validation as intended. This seems like a somewhat big issue—having to manually handle the missing value (or other native HTML constraints) checks in the validate prop in cases like this.
Provide a general summary of the issue here
I'm using the MyTextField wrapper from the React Aria documentation, and I'm trying to override some of the browser's default error messages. To do this, I pass the errorMessage prop to MyTextField. Additionally, I want to display errors coming from the backend, so I pass the validationErrors prop to the Form component.
Here’s a simplified example:
When submitting the form with an empty field, the error message "Please enter a username" displays correctly. However, since the alternative is an empty string, any other validation error (e.g., backend errors) displays nothing.
🤔 Expected Behavior?
The expected behavior is that we should be able to override specific validityState error messages without interfering with other ways the component tries to show error messages, such as backend validation errors. I know that I'm manually overriding the errorMessage the FieldError component is displaying and I might be able to do some workarounds to fix this issue, but it would overcomplicate things, It really shouldn't be this way.
😯 Current Behavior
Checkout the example sandbox I have provided below and do these: First try to submit the form with an empty field and you will see the custom error for valueMissing state, then enter some value (this example will always return an error from the fake backend) and press submit and you'll see that the error from the Form's validationErrors prop won't be displayed, but it will be displayed if you comment the errorMessage prop on MyTextField component
💁 Possible Solution
No response
🔦 Context
No response
🖥️ Steps to Reproduce
This is the sandbox I made so you can see this issue
Version
react-aria-components: 1.3.1
What browsers are you seeing the problem on?
Firefox, Chrome, Safari, Microsoft Edge, Other
If other, please specify.
No response
What operating system are you using?
Windows 11
🧢 Your Company/Team
No response
🕷 Tracking Issue
No response