I've got an Artist page in SvelteKit. Its route looks like the following:
routes
artists
[slug]
+page.server.js
+page.svelte
new
+page.server.js
+page.svelte
...
I've abstracted the form itself into a component called ArtistForm.svelte
, for the purposes of this issue I'll show just one field:
<script>
export let formData;
export let mode = "new";
</script>
<form method="POST" use:enhance>
{#if (mode !== "new") }
<input type="hidden" name="id" value={ formData.id } />
{/if}
<!-- Row 1: name, type -->
<div class="flex flex-row">
<div class="basis-1/2 form-control w-full">
<label class="label">
<span class="label-text">Name <span class="required-field">*</span></span>
</label>
<input
name="name"
id="name"
type="text"
value={ formData?.name || "" }
class="input input-bordered w-full max-w-xs"/>
{#if formData?.errors?.name}
<label for="name" class="label">
<span class="label-text-alt text-error">{ formData?.errors.name[0]}</span>
</label>
{/if}
</div>
</div>
<div class="flex flex-row">
<button type="submit" class="btn btn-primary">{ mode == "new" ? "Save" : "Update" }</button>
</div>
</form>
So in artists\[slug]\+page.svelte
I've simply got:
<script>
import ArtistForm from "../../../components/forms/ArtistForm.svelte";
/* data returned from load function in +page.server.js */
export let data;
/* data returned from actions in +page.server.js */
export let form;
</script>
<ArtistForm formData={data} mode="edit" />
and in artists\new\+page.svelte
I've got:
<script>
import ArtistForm from "../../../components/forms/ArtistForm.svelte";
/* data returned from actions function in +page.server.js */
export let form;
</script>
<ArtistForm formData={form} mode="new" />
So far so good. The issue comes when validating the data. So the action for new looks something like:
export const actions = {
default: async ({ request }) => {
const data = Object.fromEntries(await request.formData());
const artist = artistDTO(data);
// if errors returned from building the DTO (validation errors) then return the object.
if (artist?.errors && !emptyObject(artist.errors)) {
return artist;
}
const response = await createArtist(artist);
return {
...artist,
"errors": response.errors,
}
}
};
If there are any validation errors it will return the fields plus the errors in an object.
For edit mode ([slug]) the action looks similar to the previous one.
When an error occurs on new
, then the object returned from the action is assigned to formData
so the entered fields are populated again plus there's gonna be an errors
object from which errors will be displayed.
With the new
form there are no issues.
But with the edit form ([slug]
), I've got issues. When the page first loads then the object returned from the load
method is assigned to formData
so the form is populated with that data, but when the form is submitted, then if any errors are encountered and returned from the action, that object will be assigned to form
and not to data
, and form
is not being passed into ArtistForm
, but even if I decided to pass it, I'd need to know when to pull data from data
and from form
.
How can I achieve that? Not sure if the question is not clear, please let me know if more details are needed.