0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-16 21:46:22 -05:00
astro/.changeset/mighty-stingrays-press.md
Ben Holmes 7b09c62b56
Actions: add discriminated union support (#11939)
* feat: discriminated union for form validators

* chore: changeset
2024-09-06 16:41:51 -04:00

1.8 KiB

astro
patch

Adds support for Zod discriminated unions on Action form inputs. This allows forms with different inputs to be submitted to the same action, using a given input to decide which object should be used for validation.

This example accepts either a create or update form submission, and uses the type field to determine which object to validate against.

import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';

export const server = {
  changeUser: defineAction({
    accept: 'form',
    input: z.discriminatedUnion('type', [
      z.object({
        type: z.literal('create'),
        name: z.string(),
        email: z.string().email(),
      }),
      z.object({
        type: z.literal('update'),
        id: z.number(),
        name: z.string(),
        email: z.string().email(),
      }),
    ]),
    async handler(input) {
      if (input.type === 'create') {
        // input is { type: 'create', name: string, email: string }
      } else {
        // input is { type: 'update', id: number, name: string, email: string }
      }
    },
  }),
}

The corresponding create and update forms may look like this:

---
import { actions } from 'astro:actions';
---

<!--Create-->
<form action={actions.changeUser} method="POST">
  <input type="hidden" name="type" value="create" />
  <input type="text" name="name" required />
  <input type="email" name="email" required />
  <button type="submit">Create User</button>
</form>

<!--Update-->
<form action={actions.changeUser} method="POST">
  <input type="hidden" name="type" value="update" />
  <input type="hidden" name="id" value="user-123" />
  <input type="text" name="name" required />
  <input type="email" name="email" required />
  <button type="submit">Update User</button>
</form>