Vue-formulate: Form value binding is overwritten by schema default values

Created on 22 Mar 2021  ยท  10Comments  ยท  Source: wearebraid/vue-formulate

Describe the bug
The form v-model binding is being overwritten by the value in schema, so there's no way to set a default set of values that supersedes schema.

My schema has several default values of its own to have areas of a form auto-filled e.g. checkboxes ticked and select dropdowns with a default entry. When users have filled this in and saved it, it outputs the new values which are saved to server. When a user returns to the page, I don't have any way to use v-model binding or :value to supersede the default values from schema with the users saved values from the server

To Reproduce

  1. Create a form with a schema that has default values, and a "saved config" object with differing values
  2. Load the component and observe any value setting being overridden by schema.

Reproduction
CodePen available here

Expected behavior
Any binding to the form by :values or v-model should be able to supersede the defaultValue in the schema if the values don't match. Essentially like Object.assign({}, myServerSavedValues, schemaFieldDefaultValue).

bug report

Most helpful comment

Hmm...this technique works fine for me on your example:

https://codepen.io/team/braid/pen/VwPYKKg?editors=1010

Change the lines on 75-77 if you change the values from false to true they check/uncheck โ€” those can be considered your "default values". If your schema declared the value of an input to to be foobar then you would need the model value of the checkbox to be 'foobar' (that's what value does, change the checked value). And of course if you define it as "checked" in your schema, then that is a very high priority so it will check the box, personally I would leave those checked/value attributes out of your schema (which is what I did in your codepen).

Yes it works when checked isn't used, my aim is basically to set all the default values in schema, then apply a saved "previous values config" if it exists. The problem is checkbox doesn't ever set itself as true using value: true, you need to use checked: true as well like in #391. If I use checked: true, I can no longer override the checkbox values without click being used.

The reason I use schema values is because the schema itself that I'm using has its own formatting and default values, I parse this into a VueFormulate schema with default values included, because on the user side they might have never opened the form so they won't have any saved config, but it still needs to set some values to a default (Checked/unchecked/text value with a default/etc.).

Example: I want to set a form for a property to have "isHouse: true" as a default checkbox value, unless ofcourse the user has previously set the value to false in which case their config should override the default value. If a user has never opened the form they won't have any config saved, so I need it to default to true. The reason I can't simply build a key value object and apply it is because I'm already parsing the VueFormulate schema from a custom schema from a server, so I would need to pull out all the default values including nested groups (Which could be several layers deep) and build my own "default config" object. My hope was by using value in the schema, VueFormulate would handle this for me and I'll be able to merge in my previously saved config over the schema default. In general that does work, except for checkboxes.

I think overall if #391 gets a fix and I can use value: true to tick a checkbox, this will make checkboxes consistent and I won't have any issue trying to do what I need

All 10 comments

I added some more input types in the codepen for better validation, this seems to be another error specifically related to checkboxes and handling of the values, other values to apply correctly

That's working as expected. value and v-model on individual inputs has a higher precedence over the form's v-model. If you want to set different default values, consider merging default values with the form's initial model value and not setting any value props on the inputs themselves.

If you think this behavior should change, I'd be open to hearing an argument for other modalities in a feature request for the 3.0 version ๐Ÿ‘

That's working as expected. value and v-model on individual inputs has a higher precedence over the form's v-model. If you want to set different default values, consider merging default values with the form's initial model value and not setting any value props on the inputs themselves.

If you think this behavior should change, I'd be open to hearing an argument for other modalities in a feature request for the 3.0 version ๐Ÿ‘

So the value property in schema sets a :value property on the input itself?

This seems inconsistent; in the codepen I linked the binding actually does override the value for text, number, and select inputs. Only checkboxes take the default value from schema, which isn't consistent with everything else. So the proper way should be that a schema's value overrides all other value bindings?

At the moment I'm dynamically generating the schema from server, and also fetching the users saved values from server so both objects are dynamic, what are my options? Obviously one is to loop over every value, including deep-nested values, on the users saved config and override the matching key in schema with a new default value, but is there anything less complex?

Checkboxes don't work the same way โ€”ย we mirror the functionality in HTML where the 'value' sets the checked value, and checked indicates if the input is checked or not.

Checkout the note at the top of the box input docs: https://vueformulate.com/guide/inputs/types/box/

Good luck ๐Ÿ‘

Okay, I understand that checkboxes are different, but in the codepen they're the only input that's inconsistent in which value is the highest priority.

  • Text/number/select/etc. take the form-level v-model or :value as the initial value
  • Checkboxes take the schema value as the initial value

It's just confusing that it's inconsistent, I'll have to find a consistent way to set the initial value for forms that treats checkboxes and other inputs the same.

@mfcodeworks yes, regretably HTML is inconsistent on this particular input โ€” so we opted to follow HTML since most devs are familiar with that. Open to suggestions for the next version if you think there is a better way. I would still suggest setting the default value for all inputs in a schema with the form's v-model.

export default {
  data () {
    // you can get this anywhere, from the backend, from the schema etc.
    const defaultValues = {
      a: '1234',
      b: '5678',
      c: true
    }
    // in this example, rehydratedValues would be loaded via an api request in something like asyncData if you're using nuxt, but you get the idea here I think, use the default values as the initial state for a merge.
    return {
      formModel:  { ...defaultValues, ...this.rehydratedValues }
    }
  }
}

@mfcodeworks yes, regretably HTML is inconsistent on this particular input โ€” so we opted to follow HTML since most devs are familiar with that. Open to suggestions for the next version if you think there is a better way. I would still suggest setting the default value for all inputs in a schema with the form's v-model.

export default {
  data () {
    // you can get this anywhere, from the backend, from the schema etc.
    const defaultValues = {
      a: '1234',
      b: '5678',
      c: true
    }
    // in this example, rehydratedValues would be loaded via an api request in something like asyncData if you're using nuxt, but you get the idea here I think, use the default values as the initial state for a merge.
    return {
      formModel:  { ...defaultValues, ...this.rehydratedValues }
    }
  }
}

That is more or less what I've been using, I've tried that in created, also via watcher after VueFormulate first configures the values then I apply my defaults, but it doesn't work when checkboxes are involved. As in the checkbox values don't change.

I believe its because checked overwrites everything, if I set checked: true which is the only way to default the value to true currently, there's no way for me to revert it back to false without a physical click action :/ For now I'm going to try changing from checkbox, to a select, because that does work as expected. The only issue I need to handle is I can't use false as a select value because the entire select becomes blank, rather than taking false as a literal value

Hmm...this technique works fine for me on your example:

https://codepen.io/team/braid/pen/VwPYKKg?editors=1010

Change the lines on 75-77 if you change the values from false to true they check/uncheck โ€” those can be considered your "default values". If your schema declared the value of an input to to be foobar then you would need the model value of the checkbox to be 'foobar' (that's what value does, change the checked value). And of course if you define it as "checked" in your schema, then that is a very high priority so it will check the box, personally I would leave those checked/value attributes out of your schema (which is what I did in your codepen).

Hmm...this technique works fine for me on your example:

https://codepen.io/team/braid/pen/VwPYKKg?editors=1010

Change the lines on 75-77 if you change the values from false to true they check/uncheck โ€” those can be considered your "default values". If your schema declared the value of an input to to be foobar then you would need the model value of the checkbox to be 'foobar' (that's what value does, change the checked value). And of course if you define it as "checked" in your schema, then that is a very high priority so it will check the box, personally I would leave those checked/value attributes out of your schema (which is what I did in your codepen).

Yes it works when checked isn't used, my aim is basically to set all the default values in schema, then apply a saved "previous values config" if it exists. The problem is checkbox doesn't ever set itself as true using value: true, you need to use checked: true as well like in #391. If I use checked: true, I can no longer override the checkbox values without click being used.

The reason I use schema values is because the schema itself that I'm using has its own formatting and default values, I parse this into a VueFormulate schema with default values included, because on the user side they might have never opened the form so they won't have any saved config, but it still needs to set some values to a default (Checked/unchecked/text value with a default/etc.).

Example: I want to set a form for a property to have "isHouse: true" as a default checkbox value, unless ofcourse the user has previously set the value to false in which case their config should override the default value. If a user has never opened the form they won't have any config saved, so I need it to default to true. The reason I can't simply build a key value object and apply it is because I'm already parsing the VueFormulate schema from a custom schema from a server, so I would need to pull out all the default values including nested groups (Which could be several layers deep) and build my own "default config" object. My hope was by using value in the schema, VueFormulate would handle this for me and I'll be able to merge in my previously saved config over the schema default. In general that does work, except for checkboxes.

I think overall if #391 gets a fix and I can use value: true to tick a checkbox, this will make checkboxes consistent and I won't have any issue trying to do what I need

Was this page helpful?
0 / 5 - 0 ratings