Skip to content

Instantly share code, notes, and snippets.

@imaginamundo
Last active September 20, 2024 15:38
Show Gist options
  • Save imaginamundo/f1364e36d6a40a9e53a6c8619c110072 to your computer and use it in GitHub Desktop.
Save imaginamundo/f1364e36d6a40a9e53a6c8619c110072 to your computer and use it in GitHub Desktop.
Using Astro Actions result on Svelte
import { z } from "astro:schema";
export function parseFormData<T extends z.ZodTypeAny = z.ZodNever>(
input: FormData,
schema: T,
) {
const fields: z.output<T> = Object.fromEntries(input);
const validation = schema.safeParse(fields);
if (!validation.success) {
return {
fields,
fieldErrors: parseValidationErrors(
validation.error.format() as z.ZodFormattedError<T>
),
};
}
return { fields };
}
function parseValidationErrors<T extends z.ZodTypeAny = z.ZodNever>(
errors: z.ZodFormattedError<T>,
) {
const parsedErrors: { [key in keyof z.output<T>]?: string } = {};
const keys: (keyof z.output<T>)[] = Object.keys(errors);
for (let key of keys) {
if (key === '_errors') continue;
parsedErrors[key] = errors[key]._errors[0];
}
return parsedErrors;
}
<script lang="ts">
import InputError from './InputError.svelte';
import { actions, type ActionReturnType } from 'astro:actions';
const { result }: {
result: ActionReturnType<typeof actions.getGreeting>
} = $props();
let name = $state(result?.data?.fields.name || '');
let surname = $state(result?.data?.fields.surname || '');
let email = $state(result?.data?.fields.email || '');
</script>
<form method="POST" action={actions.getGreeting}>
<label>
Name:
<input type="text" name="name" bind:value={name} />
</label>
<label>
Surname:
<input type="text" name="surname" bind:value={surname} />
</label>
<label>
E-mail:
<input type="email" name="email" bind:value={email} />
</label>
<button>Submit</button>
</form>
import { defineAction } from "astro:actions";
import { z } from "astro:schema";
import { parseFormData } from "@helpers/action";
const GreetSchema = z.object({
name: z.string().min(1, { message: "Nome é obrigatório" }),
surname: z.string().min(1, { message: "Sobrenome é obrigatório" }),
email: z
.string()
.min(1, { message: "E-mail é obrigatório" })
.email({ message: "E-mail inválido" }),
});
export const getGreeting = defineAction({
accept: "form",
handler: async (input) => {
const { fields, fieldErrors } = parseFormData<typeof GreetSchema>(
input,
GreetSchema,
);
return { fields, fieldErrors };
},
});
---
import { actions } from 'astro:actions';
const result = Astro.getActionResult(actions.getGreeting);
import Form from '@components/Form.svelte';
---
<Form result={result}/>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment