formvuelate / formvuelate

Dynamic schema-based form rendering for VueJS

Home Page:https://formvuelate.js.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support for multiple sub-entries inside a SchemaForm

uwekamper opened this issue · comments

Is your feature request related to a problem? Please describe.

FormVueLate lets you group form fields easily using SchemaForm as show in the playground example: https://formvuelate.js.org/#playground

When you enter a work address and work phone number the resulting JSON looks like this:

{
  "firstName": "Uwe",
  [...]
  "work": {
    "address": "Lindenstr. 23",
    "phone": "12345",
  }
}

This works nicely for grouping many fields that belong to one combined entry.

But how would you specify a grouping of fields that allow an arbitrary number of entries.

An example of this would be a form where need to enter all the members of your family:

  • Family members:
  • [Button: Add another family member to list]
    • Select role: [ parent v ] // you can select from "parent", "grand-parent", "child", "grand-child"
    • First name: ___________________
    • Last name: ___________________
    • Address: _____________________
    • [ Button: Remove this family member from list|

The two buttons would allow users to create new entries

The resulting JSON would look like this:

{
  "familyMembers": [
    {
      "role": "parent",
      "firstName": "John",
      "lastName": "Doe"
    },
    { 
      "role": "child",
      "firstName": "Jill",
      "lastName": "Doe"
    }
  ]
}

Describe the solution you'd like

I don't know if this supported by FormVueLate at all.

If this is easily done I would appreciate a short code example in the documentation. If it is not supported or very hard to do I would also appreciate to know.

Describe alternatives you've considered

I could not find anything in the documentation about this kind of use-case.

I tried to find examples on the web, but Google did not turn up something useful so far.

Hello @uwekamper
It would seem that this could potentially be resolved by making your schema a computed property.

  • Off the top of my head, you could set a state numberOfMembers: 1
  • When the user clicks the + you ++ this number, or -- depending on your UX
  • The computed property would then have a loop

Pseudocode:

computed: {
  schema () {
    const schema = {}
      for i < numberOfMembers
         schema['familyMember' + i] = { the form schema that controls the member stuff }
    return schema
  }
}

The takeaway here is that your schema doesnt need to be static. Making it a computed property can allow you to take it as far as you need in terms of reactivity, adding or removing fields as needed

You may or may not need this prop, depending on your use case also. So give it a look too

https://formvuelate.js.org/#prop-preventmodelcleanuponschemachange

@uwekamper did this information resolve your question?

@marina-mosti Yes, thank you for very fast reply. I will try to build a prototype with that information.

As far as I understand is that if my backend API needs a list / array of family members than I will need to do the followin:

On submit, I need to convert several "familyMember + i": entries in the "modelValue" object in to a list of familyMembers, e.g.:

formData = {"familyMember1": {"name": "Jack"}}, "familyMember2": {"name": "Jill"}}

    => convertForSubmission(formData) =>

submittedFormData = {"familyMembers": [{"name": "Jack"}, {"name": "Jill"}] }

Or is there some way to store the familyMember as a list right from the start?

I cant think of a solution that is exactly like that, but if you try something similar to:

computed(() => {
      const schema = {
        people: {
          component: SchemaForm,
          schema: [],
        },
      };

      for (let i = 1; i <= members.value; i++) {
        const name = "name" + i;

        schema.people.schema.push([
          {
            model: name,
            component: FormText,
            label: "First Name",
          },
        ]);
      }

      return schema;
    });

You get the output:

{
  "people": {
    "name1": "asdf",
    "name2": "asdf",
    "name3": "asdf"
  }
}

https://codesandbox.io/s/fvl-computed-nested-h8ssp?file=/src/App.vue