Vue - Dynamic properties from external TypeScript Class are not reactive

Viewed 744

I have a small problem, I created a package to manage forms, everything worked correctly until I needed to create a dynamic form based on an API response.

Here is the package: https://github.com/nulvem/js-form

It can be installed with npm:

npm install @nulvem/js-form

Here is my Vue component calling the Form class:

<script>
import {Form} from '@nulvem/js-form'

export default {
  data() {
    return {
      form: new Form({
        template: {
          value: null,
          validation: {
            rules: 'required',
            messages: {
              required: 'You must select the type of report'
            }
          }
        }
      })
    }
  },
  mounted() {
    this.form.template = 'random-id'

    // These data will be obtained from an API
    let fields = [
      'start_date',
      'end_date',
      'wallets',
    ]

    fields.forEach((field) => {
      let fieldData = {
        value: null,
        validation: {
          rules: 'required',
          messages: {
            required: `You must enter the field ${field.description}`
          }
        }
      }

      this.form.$addField(field, fieldData)
    })

    // Here we can only see the getter/setter of the template property that was passed when instantiating the Form class
    console.log(this.form)
  }
}
</script>

The problem is: The fields I passed to the form during the creation of new Form ({...}) instance are reactive, since when I add new fields by calling the this.form.$AddField() function the fields are not getting reactive.

The funny thing is that the construct of the Form class calls a function called this.form.$AddFields() that calls the this.form.$AddField() function several times.

Why it works inside the constructor and don't when called separated? How to fix this issue?

Any idea what might be going on? This is driving me crazy, I've been trying to find the problem for several hours and I can't find it.

Edit

As a quick fix we make a change in the package where it is possible to pass the Form instance as a third parameter to the $addFields function, so the attributes are reactive, however we would like this to work without having to pass this parameter.

2 Answers

VueJS lose the reactivity of properties that are added to your data after the render. You can read more about this, here: https://br.vuejs.org/v2/guide/reactivity.html.

A quick way to try to solve this problem is adding a this.$forceUpdate() everytime that you add a new property, but it also can bring another problems depending of your context.

Or you can try using Vue.set() method, instead of your $addField method. You can read more in the same link above.

remove the context and change this line for reactivity:

this.$initialValues[field] = fieldDeclaration.value;

=>>>

this.$initialValues[field] = fieldDeclaration.value;
this.$initialValues = Object.assign({}, this.$initialValues);
Related