1

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.

1 Answer 1

1

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>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.