ciscoheat / sveltekit-superforms

Making SvelteKit forms a pleasure to use!
https://superforms.rocks
MIT License
2.11k stars 62 forks source link

Adding form and field attributes as metadata #206

Open OllieJT opened 1 year ago

OllieJT commented 1 year ago

Is your feature request related to a problem? Please describe. Sometimes I would like to display all input fields, but disable them based on my own logic.

Examples

Describe the solution you'd like I believe it's important to define this logic where the schema is shared with superforms, in the server side superValidate function.

I expect the api could look something like this:

// schema
const schema = z.object({
   title: z.string(),
   slug: z.string(),
   is_published: z.string(),
});

// my own logic to determine what fields are disabled
// ...

// init superforms
const form = superValidate(data, schema, {
   // record (or array?) of schema keys
   disabled: {
      slug: true,
      is_published: false,
   },
});

I expect the disabled state would then be passed to each fields

$constraints = {
   title: {
      required: true,
   },
   slug: {
      required: true,
      disabled: true,
   },
   is_published: {
      required: true,
      disabled: true,
   },
};

Describe alternatives you've considered At the moment I am manually passing a similar record alongside the form, and abstracting input fields so that I can pass a disabled state to them.


I think I could work on this addition myself, but still want to make sure the approach is agreed on 👍

OllieJT commented 1 year ago

Here's a full example of my current solution for this challenge.

import { superValidate } from 'sveltekit-superforms/server';
import { z, type ZodTypeAny } from 'zod';
import type { PageServerLoad } from './$types';

const schema = z.object({
   title: z.string(),
   slug: z.string(),
   is_published: z.boolean(),
});

type FormFieldFilter<TX extends ZodTypeAny> = {
   [k in keyof z.infer<TX>]: boolean;
};

type SchemaFilter = FormFieldFilter<typeof schema>;

export const load: PageServerLoad = async () => {
   const is_superadmin = true;

   const data = {
      title: 'My fake article',
      slug: 'my-fake-article',
      is_published: false,
   };

   const form = superValidate(data, schema);

   const form_disabled = {
      // not disabled
      title: false,

      // disabled
      slug: true,

      // disabled if not superadmin
      is_published: !is_superadmin,
   } satisfies SchemaFilter;

   return {
      form,
      form_disabled,
   };
};
ciscoheat commented 1 year ago

This is related to #36, where the idea is that form attributes are also added on the server. So combining it with yours, it seems like there is form "metadata" (unrelated to the Superforms stores) that is sometimes advantageous to pass from the server to the client. Basically attributes for a form element, and also attributes for the form fields.

For this to be a generic solution, it requires some thought, so lets keep discussing it here.

denartha10 commented 1 year ago

Hi @OllieJT.

I recently wanted to add form metadata similar to above except it would be more related to the type of field input is being used for each field allowing dynamically generated forms.

I really like your solution above and was hoping you could tell me if you’ve since expanded on this maybe created your own object containing metadata also compatible with superValidate?

ciscoheat commented 1 year ago

@denartha10 until this is resolved, you can introspect the Zod schema to get the type of the schema fields. Here's an example:

https://stackblitz.com/edit/sveltekit-superforms-1-testing-mvqpy4?file=src%2Froutes%2F%2Bpage.svelte

alexbjorlig commented 9 months ago

Hi @ciscoheat - I'm trying to adopt superforms in our project, and was a bit surprised to not find any built-in support for disabling fields or the entire form?

Did I miss something, or is it a feature you would like to see in the project?

I would be happy to take a look at adding a PR to support this.

ciscoheat commented 9 months ago

Hi, since there's no information in the schema to indicate that fields, or the whole form, should be disabled, so how did you envision it to work?

ciscoheat commented 9 months ago

To be more precise, I don't want to add features that can just as easily be sent as extra data in the load function. How to make this extra data purposeful with forms is the challenge.