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>