Conversation
|
@mirka @jameskoster There's this use case where the DataForm field needs to make a query to an endpoint to run some validation logic, which requires validation to be async. One thing I've noticed with this approach is that there's no communication to the user that validation is being processed asynchronously. Do you have any thoughts on this? Perhaps we could make the ControlWithError component display a yellow message such as "validating..." or something along those lines? |
Yeah the delay in validation stood out to me and doesn’t seem ideal. A very short delay is probably okay, but anything more than ~300ms would benefit from some visual feedback. I suppose we could add |
|
However, I'm wondering whether even that is necessary 🤔 I think we've decided not to show an explicit "validated ✅" state, which kind of means that input is assumed to be valid in most cases, and we only give any kind of feedback when truly necessary. In that sense, adding a "validating ⌛" state kind of highlights the fact that there's validation going on, and almost forces the user to keep their attention there until a result is returned, even though it'll be valid in most cases. And then we don't even show a ✅ state. So maybe we can just be optimistic there and not show a waiting state at all. But then again, there will sometimes be fields where most input is actually invalid — I'm thinking like a username field in a sign up form. Then maybe we do need a waiting state and an explicit ✅ state for these cases. @jameskoster Let me know if we want to try the waiting state, and I'll try to spin up a prototype at the component level. |
|
Good points there! I agree, without confirmation (when the input is valid) the purpose of the spinner is unclear and could even seem broken. But with that said a long delay without any feedback makes the UX feel unresponsive. The videos in the OP where there’s a noticeable delay in validation seem really clunky to me. In examples like user name fields I suspect most users expect validation to take a second, so showing a waiting state and ‘Valid’ message seems reasonable to me. Perhaps this is true for most async inputs, do we have other real-world examples? If so, maybe async validation inputs have slightly different rules? E.g:
|
|
I have a demo going in #71184 |
59b1b0b to
ed5952c
Compare
|
@mirka @jameskoster I've updated this PR to leverage #71184 Would you be able to give me a confidence check about direction before I update every DataForm control? This is the current state: Screen.Recording.2025-08-19.at.11.50.51.movA few things in my mind:
Screen.Recording.2025-08-19.at.12.00.45.mov
Screen.Recording.2025-08-19.at.12.01.15.mov |
|
Flaky tests detected in ed5952c. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/17065866542
|
Seems reasonable to try.
I'm not entirely sure why that is happening, but @mirka will have a better idea. |
Ok, I'll try adding this behavior in the components. Though, I wonder if it will be annoying with the layout shifts, given that the user will likely be interacting with the rest of the form when the "Validated ✅" indicator unmounts.
Thanks for catching. I've identified the bug — proposed fix in #71260.
We decided on this global behavior as part of the initial specs. Is your concern about firing too many server calls? If so, I think that should be dealt with by debouncing the call. (I think the reasoning for this validation timing logic was that it's not necessarily obvious to the user that they need to blur the field for it to revalidate.) |
Yeah, I was thinking that validating on blur is not clear. This is more visible in forms with a single field to validate: for example, quick edit or action modals (the current examples we have in the site editor). Users need to click outside the control for it to trigger validation in those scenarios. |
ed5952c to
092c1ef
Compare
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Is something like #71282 useful in these cases? |
|
Yeah, that highlights a few things we need to fix in the validation flow when we use the panel layout: Screen.Recording.2025-08-21.at.18.49.43.mov
In any case, I think it's a different conversation: even if we switched from validating onBlur to validate upon interaction, the issues would persist (though it'd perhaps clearer that field is invalid). |
Another advantage of explicit save/cancel buttons is that we can make it so users can naturally submit the value and dismiss the popover with the Enter key. Right now you'd have to hit Escape to close, even you want to commit the value. |
|
Yeah, I think the UX is clearer with the buttons. Another option would be to combine both approaches outlined in my previous comment; Dialog title + close button + explicit buttons. Basically a mini modal. But I know there has been a lot of visual design pushback on including buttons like this in the past so I'd welcome feedback from @WordPress/gutenberg-design before committing. |
092c1ef to
2d50200
Compare
|
Switching this to draft again because I'm incorporating some logic coming from #71345 |
2d50200 to
d61877f
Compare
d61877f to
e52acd2
Compare
|
Worked a bit on this today. I may split this PR is smaller ones when direction is clear, but I wanted to solve a few things we need to address: validation needs to run only once, it needs to support sync and async modes, and consumers need to receive the validation status (so they can control things outside DataForm's scope, such as a "save button"). Screen.Recording.2025-08-27.at.19.17.54.mov(For context: the 1st approach to validation exposed a The current proposal:
Things to address/clarify about direction:
cc @mirka @youknowriad for thoughts, as I've been discussing separate things with both of you. Hope this is context enough and not too long. |
| disabled={ isFormBusy || ! isFormValid } | ||
| isBusy={ isFormBusy } |
There was a problem hiding this comment.
Can a button be busy and disabled, @mirka? Note this weird interaction:
- Button is disabled because form is invalid.
- Some interaction triggers an async validation: button becomes busy, and changes appearance to "active".
- Async validation resolves and button goes back to invalid.
Screen.Recording.2025-08-27.at.19.22.06.mov
|
I paired with Riad to discuss the current approach (validation is uncontrolled by the consumers, they receive the status via
Riad suggested we could try a controlled approach to validation (the consumer passes the validation status via prop):
|
Here's the PR #71412 It works for sync validation, I need to update it to also cover async. |
|
We're going to go with #71412 instead |



See alternative PR at #71412
What?
This PR enables customers to use async custom validation.
Why?
Some validation may happen in the server, so consumers need the ability to make async calls.
How?
isValid.customcan return a Promise.isItemValidwork async.Testing Instructions
npm install && npm run storybook:dev).Screen.Recording.2025-08-20.at.14.34.21.mov