Closed L-Mario564 closed 4 months ago
Now, custom FormError
exceptions can be thrown within the the submit
function in the form component to have it be displayed in the UI. For example:
If this errors:
if (!isNameUnique) {
throw new FormError(`Staff role "${value.name}" already exists in this tournament.`);
}
It display as such:
If any other exception is thrown, the error modal will appear and the form component will unmount.
Will be handled differently, but taking a lot of inspiration from this implementation.
Aims to solve and implement #11.
The main issues with the current implementation of forms can be summed up in this paragraph mentioned in the above issue:
This PR has the goal of improving dyamic forms.
How would I create a new form now?
Let's take the same example as the mentioned issue, which is about creating new staff role. In the
+page.svelte
file, we'd include this:src/routes/tournament/[tournamentId]/manage/staff/roles/+page.svelte
Each argument has its purpose, for the most part, it should be clear what each does, like
afterSubmit
runs after the form's submission. In this case, we're selecting the created staff role we just created in the dashboard.onFormReopen
runs when an error is thrown and the user closes the error message. In this case, duplicate staff role names aren't allowed, so it will throw an error if a role with that name already exists. After the user closes the error message, the form will reopen with the previous data so they don't have to reinput everything and make the necessary changes from there.Each property has JSDoc comments written in the
form
store file (src/lib/stores/form.ts
) which you can take a look for more info.Oh, and
createStaffRole
is just an alias forcreate
, with the benefit of adding types specific to the create staff role form. To achieve this for another form, we just add it to the form registry which is just a Typescript type.src/forms/registry.ts
Now, onto the form itself.
src/forms/CreateStaffRole.svelte
Here we handle pretty much everything, form layout, validation, creating types specific to the form (which we saw is used in the registry) and also the submission itself, with the
submit
function having included utilities commonly used in other forms, like the tRPC client, the current page store, theinvalidateAll
function and the context, which we passed in the+page.svelte
file as this file doesn't know about the tournament ID, but requires it to submit the form. These utilities are present to avoid importing commonly used utilities cross different forms.This new implementation separates the concerns between pages and forms, and by making it a component, you introduce any custom elements you want inside the
Form
component, all while still keeping everything that used to work with the previous implementation, including the type safety.