Let the event form submit and say what is wrong #177

Merged
padreug merged 1 commit from fix/submit-gate-explains-itself into dev 2026-09-29 08:02:09 +00:00
Owner

Found on demo while testing #176: a fully filled event form — title, dates, price, capacity, payment methods, a promo code and three named ticket waves — with the Submit button greyed out and nothing on screen explaining why.

It isn't the wave validation

First thing I checked, since #176 added a wave gate. It isn't: running the exact form contents through the validators gives WAVE ERRORS: {} and PROMO ERRORS: [{}]. The blocker was vee-validate's meta.valid, which predates that PR.

Gating on meta.valid is the actual bug

It's a known foot-gun, and this dialog hits every part of it:

  • Disabled fields count against validity. The docs are explicit that "disabled fields are not necessarily valid... they affect the Form meta just like other fields" — disabled was removed from <Field> because consistent behaviour was unachievable. This dialog disables inputs while loading and renders fiat_currency conditionally.
  • It goes stale. #4630 reports meta.valid staying false with zero errors after a form is re-shown.
  • It's false before the form has ever validated, which is why the docs suggest valid && dirty rather than valid.

A flag that's unreliable in both directions shouldn't be the only thing between an organiser and their event — especially as a disabled button, which is an unrecoverable dead end with no affordance for finding out why.

What changes

The button is disabled only while a submit is genuinely in flight. The reasons now come to the user:

  • handleSubmit's invalid callback names the offending fields in a toast, opens whichever collapsible holds one, and scrolls the first into view. Previously a FormMessage inside a closed section was invisible — and notification_subject isn't rendered at all, so its error could never have been seen.
  • Promo codes and ticket waves aren't in the Zod schema, so vee-validate can't block on them. They're checked in the submit handler, which opens their section rather than returning silently. Both editors live inside collapsibles, so this was the same trap — and it's one #176 introduced for waves, so it's fixed here rather than left.

Verified in a browser

submit present: 1 | ENABLED blank: True
post-click → "Check Tickets, Start date, Title"

A blank form has a live button, and clicking it reports exactly what's missing. 72 tests pass, vue-tsc clean, prettier clean, production build succeeds.

Note for whoever is blocked right now

Until this deploys, the offending field is still discoverable — FormControl sets aria-invalid, so this in the console names it:

[...document.querySelectorAll('[aria-invalid="true"]')].map(e => e.id || e.name)

Sources: Handling Forms · #4630 · #1109

Found on demo while testing #176: a fully filled event form — title, dates, price, capacity, payment methods, a promo code and three named ticket waves — with the Submit button greyed out and **nothing on screen explaining why**. ## It isn't the wave validation First thing I checked, since #176 added a wave gate. It isn't: running the exact form contents through the validators gives `WAVE ERRORS: {}` and `PROMO ERRORS: [{}]`. The blocker was vee-validate's `meta.valid`, which predates that PR. ## Gating on `meta.valid` is the actual bug It's a known foot-gun, and this dialog hits every part of it: - **Disabled fields count against validity.** The docs are explicit that *"disabled fields are not necessarily valid... they affect the Form meta just like other fields"* — `disabled` was removed from `<Field>` because consistent behaviour was unachievable. This dialog disables inputs while loading and renders `fiat_currency` conditionally. - **It goes stale.** [#4630](https://github.com/logaretm/vee-validate/issues/4630) reports `meta.valid` staying false with zero errors after a form is re-shown. - **It's false before the form has ever validated**, which is why the docs suggest `valid && dirty` rather than `valid`. A flag that's unreliable in both directions shouldn't be the only thing between an organiser and their event — especially as a *disabled button*, which is an unrecoverable dead end with no affordance for finding out why. ## What changes The button is disabled only while a submit is genuinely in flight. The reasons now come to the user: - `handleSubmit`'s **invalid callback** names the offending fields in a toast, opens whichever collapsible holds one, and scrolls the first into view. Previously a `FormMessage` inside a closed section was invisible — and `notification_subject` isn't rendered at all, so its error could never have been seen. - **Promo codes and ticket waves aren't in the Zod schema**, so vee-validate can't block on them. They're checked in the submit handler, which opens their section rather than returning silently. Both editors live inside collapsibles, so this was the same trap — and it's one #176 introduced for waves, so it's fixed here rather than left. ## Verified in a browser ``` submit present: 1 | ENABLED blank: True post-click → "Check Tickets, Start date, Title" ``` A blank form has a live button, and clicking it reports exactly what's missing. 72 tests pass, `vue-tsc` clean, prettier clean, production build succeeds. ## Note for whoever is blocked right now Until this deploys, the offending field is still discoverable — `FormControl` sets `aria-invalid`, so this in the console names it: ```js [...document.querySelectorAll('[aria-invalid="true"]')].map(e => e.id || e.name) ``` Sources: [Handling Forms](https://vee-validate.logaretm.com/v4/guide/components/handling-forms) · [#4630](https://github.com/logaretm/vee-validate/issues/4630) · [#1109](https://github.com/logaretm/vee-validate/issues/1109)
The Submit button was disabled on `meta.valid`, so an organiser with a
fully filled form could be left staring at a dead button with nothing on
screen explaining it. Reported from demo: title, dates, price, capacity,
payment methods and three named ticket waves all filled, no error text
anywhere, submit greyed.

Gating on `meta.valid` is a known vee-validate foot-gun:

- disabled fields count against form validity, and the maintainer
  removed `disabled` from `<Field>` precisely because consistent
  behaviour was unachievable. This dialog disables inputs while loading
  and renders `fiat_currency` conditionally, so it is exposed.
- `meta.valid` is documented to go stale — false with zero errors after
  a form is re-shown (logaretm/vee-validate#4630).
- it is false before the form has ever validated, which is why the docs
  suggest `valid && dirty` rather than `valid` alone. A flag that is
  unreliable in both directions should not be the only thing between an
  organiser and their event.

So the button is now disabled only while a submit is genuinely in
flight, and the reasons come to the user instead:

- `handleSubmit`'s invalid callback names the offending fields in a
  toast ("Check Tickets, Start date, Title"), opens whichever collapsible
  holds one, and scrolls the first into view. Previously a FormMessage
  inside a closed section was invisible.
- promo codes and ticket waves are not in the Zod schema, so
  vee-validate cannot block on them; they are checked in the submit
  handler, which opens their section rather than failing silently. Both
  editors live inside collapsibles, so this was the same trap.

Verified in a browser: a blank form now has an enabled button, and
clicking it reports "Check Tickets, Start date, Title".

Refs aiolabs/events ticket-wave work; the report came from testing #176
on demo.
padreug deleted branch fix/submit-gate-explains-itself 2026-09-29 08:02:09 +00:00
Sign in to join this conversation.
No description provided.