vee-validate icon indicating copy to clipboard operation
vee-validate copied to clipboard

Multiple independent forms on a single page

Open zluiten opened this issue 3 years ago • 15 comments

I'm using v4 with the composition api. I don't quite understand how the useForm and useField functions relate to each other.

Currently I'm having multiple small forms on the same page, each with a few fields, maybe even sharing an input field with the same name. I would expect to be able to define some kind of context (a form html element reference?) to be able to set some initial values.

Or do I need to split this page up in sub components to achieve this?

zluiten avatar Mar 04 '21 21:03 zluiten

This is one of the inherited issues with the composition API in general, not specific to vee-validate.

Typically you need to split them up into multiple smaller components, or turn to the <Field/> or <Form/> components as they are ideal for these scenarios.

In the early Alphas I experimented with explicit forms, where you would pass the form object to the useField to designate it as part of that form, maybe I can bring it back with some enhancements.

logaretm avatar Mar 04 '21 21:03 logaretm

Thanks @logaretm! Even though splitting up in to smaller components is a better approach and a good practice, it doesn't feel right to be forced to do so.

When I started with the composition API approach, it felt like magic how initialValues is passed to inputs associated with the useForm function. I definitely would favor some (optional?) explicit binding to make things clear and more understandable.

By the way, thanks for all the support and effort you put into this library! My question has been answered, shall I close this issue or do you want it open for future reference?

zluiten avatar Mar 05 '21 10:03 zluiten

it doesn't feel right to be forced to do so

I share your sentiment here, basically this was possible in previous alphas:

const form1 = useForm();
const form2 = useForm();

const field = useField('somefield', undefined, {
  form: form1
});

But didn't like the style because it would encourage doing messy setup functions.

shall I close this issue or do you want it open for future reference?

Let's keep it open for now, I plan to experiment with some ideas for this.

logaretm avatar Mar 05 '21 11:03 logaretm

I just realized you can't have a main Form, with many nested Form's and have the ability to validate all of them at once (the main Form). I have a component, with many sub-components with their own <Form>. I can't validate the parent <Form> if there are nested <Form>'s. Will this be possible in the future? Version 1-3 you were able to do this.

Speedy059 avatar Mar 10 '21 19:03 Speedy059

@Speedy059 That's a different use case, in v4 I have no intention to introduce nested forms as maintaining that heap of crap was very consuming in v2 and v3.

I never actually used scopes in v2 or nested observers in v3 which made me re-evaluate their usefulness for v4, what you are looking to do is aggregate form information and stitch them together, which can be easily done in user-land with the composition API.

Check the issue here which discussed this briefly

logaretm avatar Mar 10 '21 20:03 logaretm

@logaretm I use multiple fields on a page in separate sub-components with useField. When validation error occurs and the input field is empty then something weird happen - an error message from different neighbouring component is displayed which shouldn't happen as they are independent from each other. They have different names and all the composition functions I use in setup() are originating from useField. Is this a bug, or I'm doing something wrong?

JoJk0 avatar Mar 16 '21 19:03 JoJk0

@JoJk0 Without a minimal example it would hard to tell you what's going on, but the way useField works is that it searches for the nearest form context created by either useForm or <Form /> in the parent hierarchy, which what might be happening on your end.

logaretm avatar Mar 17 '21 06:03 logaretm

@logaretm would be good to mention in the documentation that using multiple userForm() in a single component will not work atm (just spent some time figuring out why my validation was not working...).

Will put my forms in separate components for the time being.

chrisb-c01 avatar Apr 09 '21 14:04 chrisb-c01

Is there a solution for this? My setup is:

<parent>
  <child>
    <form2>
    </form2>
  </child>
  <form>
  </form>
</parent>

The child's fields are automatically added to Form in the parent, what can I do to prevent this?

Pretty common use-case, a form, and then a modal on the page with it's own form, the traversal should only be searching direct parents? Not uncles or siblings?

nick-barth avatar Feb 02 '22 12:02 nick-barth

@logaretm I understand not wanting to mess with a config object on top of useField in your example as it does seem messy

const form1 = useForm();
const form2 = useForm();

const field = useField('somefield', undefined, {
  form: form1
});

But maybe it would be possible to expose a useField function from useForm that always has the context of that form? I'm not sure how it works under the hood.

const form1 = useForm();
const form2 = useForm();

const field = form1.useField('somefield')

DoubleJ-G avatar Feb 22 '22 05:02 DoubleJ-G

@DoubleJ-G Thanks for the suggestion, your suggested API has another benefit as it allows for typing the field name as mentioned here #3375

This is something to do for 4.6 probably.

logaretm avatar Feb 22 '22 15:02 logaretm

Hi @logaretm , looking forward to find this feature in next release.

SmogUA avatar Jun 10 '22 08:06 SmogUA

A couple of updates on this:

  • Using useField to create models should no longer be encouraged since this isn't its intended use case but I will work on adding logic to allow for this.
  • New API is already merged on main which exposes a similar function called useFieldModel on the Form context object.
const form1 = useForm();
const form2 = useForm();

const [email, password] = form1.useFieldModel(['email', 'password']);
const [firstName, lastName] = form1.useFieldModel(['firstName', 'lastName']);

The useFieldModel will be the recommended way if you plan to use v-model instead of creating field components with useField.

logaretm avatar Jun 13 '22 07:06 logaretm

Hi @logaretm, i set validationSchema, validateOnMount false to form and useFieldModel, it will validate fields at updated hook then display errors, is it possible to prevent validate when form initial mounted? My link is below.

https://stackblitz.com/edit/vee-validate-v4-starter-composition-example-tcdkkt?file=src%2FApp.vue

Many thanks.

yzukiori avatar Aug 17 '22 07:08 yzukiori

@logaretm nice!

Small detail: you probably want to show that firstName and lastName can be managed by form2 (your example uses form1).

const [firstName, lastName] = form2.useFieldModel(['firstName', 'lastName']);

zluiten avatar Aug 18 '22 07:08 zluiten