Home > Software engineering >  How to setup conditional field from json within vuejs
How to setup conditional field from json within vuejs

Time:01-16

What is the best way to create a condition in a form from a dynamic scheme?

I am using a json list to setup my form, within my json list I wanna add a function where I can validate some logic to check if the field should be visible/required or not, or for example to validate the value with other value from the form.

This is a part of my json form:

..
  "colour": {
    compType: 'radiobox',
    label: 'Colour',
    options: [
      { value: 'red', label: 'Red' },
      { value: 'green', label: 'Green' },
      { value: 'blue', label: 'Blue' },
    ],
  },
  "model" : {
    condition: testCondition,  <----(Function which returns true if the field colour is red)
    compType: 'select',
    label: 'Role model',
    subLabel: 'Who do you look up to?',
    options: [
      { value: '', label: 'Select one', disabled: true },
      { value: 'captain-america', label: 'Steve Rogers/Captain America' },
      { value: 'iron-man', label: 'Tony Stark/Iron Man' },
      { value: 'thor-odinson', label: 'Thor Odinson' },
      { value: 'the-hulk', label: 'Bruce Banner/The Hulk' },
      { value: 'black-widow', label: 'Natasha Romanoff/Black Widow' },
      { value: 'hawkeye', label: 'Clint Barton/Hawkeye' },
    ],
  },
..

Then I walk through it via my template.

...
      <q-select v-else-if="prop.compType === 'select' && prop.condition" 
        outlined
        v-model="dataRef[key]"
        :options="prop.options"
        :label="prop.label"
        >
      </q-select>
...

And the function should look something like this:

const testCondition = () => {
  //how can I reach my ref Form data to check if the field needs to be visible
}

But because the form is not initialized yet I get an "Cannot access before initialization" error. Can someone help me on the right track? Will be more than enough for me.

PS: I know there are libraries that do this, but I'd rather I learn and understand it myself.

CodePudding user response:

Please take a look at following snippet (you can extend testCondition function to all required cases):

const { ref, onMounted } = Vue
const app = Vue.createApp({
  setup () {
    const fields = [{
      compType: 'radiobox',
      label: 'Colour',
      model: 'color',
      options: [
        { value: 'red', label: 'Red' },
        { value: 'green', label: 'Green' },
        { value: 'blue', label: 'Blue' }
      ]
    },
    {
      condition: true,  
      compType: 'select',
      model: "role",
      label: 'Role model',
      subLabel: 'Who do you look up to?',
      options: [
        { value: '', label: 'Select one', disabled: true },
        { value: 'captain-america', label: 'Steve Rogers/Captain America' },
        { value: 'iron-man', label: 'Tony Stark/Iron Man' },
        { value: 'thor-odinson', label: 'Thor Odinson' },
        { value: 'the-hulk', label: 'Bruce Banner/The Hulk' },
        { value: 'black-widow', label: 'Natasha Romanoff/Black Widow' },
        { value: 'hawkeye', label: 'Clint Barton/Hawkeye' }
      ]
    }
  ]
  const dataRef = ref({})
  const testCondition = (id) => {
    if(id === 'role') {
      if(dataRef.value.color === 'red') {
        dataRef.value.role = null
        return false
      }
      return true
    }
  }
  onMounted(() => {
    for(field of fields) {
      dataRef.value[field.model] = null
    }
  })
  return { testCondition, dataRef, fields }
  }
})

app.use(Quasar)
app.mount('#q-app')
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material Icons" rel="stylesheet" type="text/css">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/quasar.prod.css" rel="stylesheet" type="text/css">

<div id="q-app">
  <div v-for="(prop, key) in fields" :key="key">
    <q-option-group v-if="prop.compType === 'radiobox' && (prop.condition ? testCondition(prop.model) : true)"
      :options="prop.options"
      type="radio"
      v-model="dataRef[prop.model]"
    ></q-option-group>
    <q-select v-if="prop.compType === 'select' && (prop.condition ? testCondition(prop.model) : true)"
      outlined
      v-model="dataRef[prop.model]"
      :options="prop.options"
      :label="prop.label"
      >
    </q-select>
  </div>
  {{dataRef}}
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/quasar.umd.prod.js"></script>

  • Related