I am new to Vuejs and I am using Vue 3 with composition API. I am creating a Yup schema through custom fields. The problem I am facing that how can I add/assign dynamically created Yup schema to useForm().
Currently, what I have tried so far. I have created a function that returns Yup Shape, which I assign to useForm. Right now this code successfully creates schema within getCustomFieldsData. But I try to access it in the template it's always empty. As in code, it tries declaring variables and assigning them but remains empty. Any help or direction would be a great help.
<template>
<div class="container-fluid">
<Loading v-model:active="isLoading">
</Loading>
<div class="page-header">
<div class="row">
<div class="col-sm-6">
<div class="page-header-left">
<h3>
Add/Edit Asset Category
</h3>
</div>
</div>
<div class="col-sm-6">
<ol class="breadcrumb pull-right">
<li class="breadcrumb-item">
<router-link to="/dashboard">
<i class="fa fa-home"></i>
</router-link>
</li>
<li class="breadcrumb-item"><router-link to="/assetcategorylist">Manage Assets
Category</router-link></li>
<li class="breadcrumb-item active">Add/Edit Asset Category</li>
</ol>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-body admin-form">
<Form :validation-schema="schema">
<template v-for="item of formControlList">
<h3 class="heading-partition">{{ item.group_display_name }}</h3>
<code>{{ errors1 }}</code>
<div class="row">
<template v-for="inner of item.InnerData">
<div :class="{
'col-sm-12 col-md-12 float-left': true, 'col-12': inner.layout_type == 'single', 'col-md-6': inner.layout_type == 'double', 'col-lg-4': inner.layout_type == 'triple', 'col-lg-3 col-xl-3':
inner.layout_type == 'four'
}">
<!---->
<input type="hidden" v-if="inner.form_field_visibility == 'NO'" />
<!--v-model="item.value" v-bind:id="item.name" -->
<label
v-if="inner.form_field_visibility == 'YES' || inner.edit_form_field_visibility == 'YES'">{{
inner.display_name }}:<span class="text-danger"
:class="{ 'text-danger': inner.is_required == true }"
v-if="inner.is_required == true">*</span></label>
<div class="form-group"
v-if="inner.form_field_visibility == 'YES' || inner.edit_form_field_visibility == 'YES'">
<div id="profile_thumb_upload" class="custom-file w-100"
v-if="inner.dt_code == 'imageurl'">
<input class="form-control" type="file" ref="file" @change="setFile"
accept="image/x-png,image/gif,image/jpeg" lang="es" />
</div>
<input type="text" class="form-control" :readonly="inner.is_readOnly"
v-model="fieldData[inner.form_controlName]" :id="inner.custom_field_id"
v-if="inner.picklist_options != 'Lookup' && inner.dt_code != 'datetime' && inner.dt_code != 'date' && inner.dt_code != 'radio' && inner.dt_code != 'boolean' && inner.dt_code != 'select' && inner.dt_code != 'textarea' && inner.dt_code != 'checkbox' && inner.dt_code != 'date' && inner.dt_code != 'int' && inner.dt_code != 'decimal' && inner.dt_code != 'bigint' && inner.dt_code != 'imageurl'" />
<input type="text" class="form-control" :readonly="inner.is_readOnly"
v-model="fieldData[inner.form_controlName]" :id="inner.custom_field_id"
v-if="inner.dt_code == 'datetime'" [value]="inner.value" />
<input type="text" class="form-control" :readonly="inner.is_readOnly"
v-model="fieldData[inner.form_controlName]" :id="inner.custom_field_id"
v-if="inner.dt_code == 'int'" />
<!-- <small v-if="inner.dt_code == 'int' && (form.get(inner.form_controlName).touched &&
form.get(inner.form_controlName).errors?.pattern)"
class="text-danger">Please enter valid
value</small> -->
<input type="text" class="form-control" :readonly="inner.is_readOnly"
v-model="fieldData[inner.form_controlName]" :id="inner.custom_field_id"
v-if="inner.dt_code == 'bigint'" />
<!-- <small v-if="inner.dt_code == 'bigint' && (form.get(inner.form_controlName).touched &&
form.get(inner.form_controlName).errors?.pattern)"
class="text-danger">Please enter valid
value</small> -->
<input type="text" class="form-control" :readonly="inner.is_readOnly"
v-model="fieldData[inner.form_controlName]" :id="inner.custom_field_id"
v-if="inner.dt_code == 'decimal'" />
<!-- <small v-if="inner.dt_code == 'decimal' && (form.get(inner.form_controlName).touched &&
form.get(inner.form_controlName).errors?.pattern)"
class="text-danger">Please enter valid
value</small> -->
<textarea class="form-control" v-if="inner.dt_code == 'textarea'"
v-model="fieldData[inner.form_controlName]" rows="3"
cols="4"></textarea>
<p-calendar inputStyleClass="form-control start-date"
v-if="inner.dt_code == 'date'"
v-model="fieldData[inner.form_controlName]" [showTime]="false"
dateFormat="mm/dd/yy" showButtonBar="true" [monthNavigator]="true"
[yearNavigator]="true" yearRange="1919:2030"></p-calendar>
<div class="form-control pl-0 border-0 bg-transparent"
v-if="inner.dt_code == 'checkbox'">
<div v-for="options of inner.listoptions">
<div class="form-check form-check-inline"
v-for="option of options.listoptions" :index="index">
<div class="custom-control custom-checkbox">
<input
id="chk_{{inner.custom_field_id}}_{{option}}_{{index}}"
value="5555" [checked]="checkvalue(inner.value,option)"
(change)="onCheckboxChange($event,item,inner)"
class="dynamic custom-control-input" type="checkbox">
<label
class="custom-control-label universal-custom-control-label pl-2 pr-1 dynamic"
for="chk_{{inner.custom_field_id}}_{{option}}_{{index}}">{{
option }}</label>
</div>
</div>
</div>
</div>
<div class="form-control pl-0 border-0 bg-transparent"
v-if="inner.dt_code == 'boolean'">
<input class="form-check-input" type="checkbox"
v-model="fieldData[inner.form_controlName]" id="gridCheck">
<label class="form-check-label" for="gridCheck">
Is Active?
</label>
</div>
<!--Radio button-->
<div class="form-control pl-0 border-0 bg-transparent"
v-if="inner.dt_code == 'radio'">
<div v-for="options of inner.listoptions">
<div class="form-check form-check-inline"
v-for="option of options.listoptions" :index="index">
<div class="custom-control custom-radio mx-2 p-0">
<input id="radio-{{inner.custom_field_id}}_{{option}}"
v-model="fieldData[inner.form_controlName]"
[value]="option" type="radio">
<label for="radio-{{inner.custom_field_id}}_{{option}}"
class="radio-label">{{ option }}</label>
</div>
</div>
</div>
</div>
<ng-select [items]="inner.select_options"
:class="{ 'disabledddl': inner.is_readOnly }"
:id="inner.form_controlName" [closeOnSelect]="true" placeholder="Select"
v-if="inner.dt_code == 'select' && inner.picklist_options == ''"
v-model="fieldData[inner.form_controlName]" bindLabel="name"
bindValue="value">
</ng-select>
<ng-select [items]="inner.select_options"
:class="{ 'disabledddl': inner.is_readOnly }"
:id="inner.form_controlName" [closeOnSelect]="true" placeholder="Select"
v-if="inner.dt_code == 'select' && inner.picklist_options == 'true'"
v-model="fieldData[inner.form_controlName]" [multiple]="true"
bindLabel="name" bindValue="value">
</ng-select>
<!-- <small
v-if="((form.get(inner.form_controlName)?.invalid) && (form.get(inner.form_controlName).dirty) || (form.get(inner.form_controlName)?.touched) && (form.get(inner.form_controlName)?.errors?.required))"
class="text-danger">{{ inner.display_name }} is required</small> -->
</div>
</div>
</template>
</div>
<div class="form-btn">
<a href="javascript:;" class="btn btn-pill btn-gradient color-4" @click="onSubmit()"
style="width:max-content">Submit</a>
<a href="javascript:;" class="btn btn-pill btn-dashed color-4"
@click="Cancel">Cancel</a>
</div>
</template>
</Form>
<AssetAttributelist></AssetAttributelist>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { ref, onMounted, onBeforeMount } from "vue";
import { Form, Field, useField, useForm } from 'vee-validate';
import DynamicSelect from '@/views/shared/singleSelect/singleDrp.vue';
import InputMask from '@/views/shared/inputmask/inputmasktemplate.vue';
import createYupSchema from '@/views/shared/common/yupSchemaCreater';
import * as Yup from 'yup';
//Services
import AssetCategoryService from "@/service/crmservice/assetcategoryservice";
import CommonService from "@/service/crmservice/commonService";
//Components
import AssetAttributelist from "@/views/crm/assetcategory/categoryattributelist.vue"
export default {
name: 'addeditassestcategory',
components: {
"dynamic-select": DynamicSelect,
InputMask,
Form,
Field, AssetAttributelist
},
setup(props) {
const assetCategoryService = ref(new AssetCategoryService());
const commonService = ref(new CommonService());
const primaryKey = ref(null);
const userId = ref(null);
const companyId = ref(null);
const moduleCode = ref('6001');
const subModuleCode = ref('6001');
const otherData = ref(null);
const refId = ref(null);
const displayCode = ref('Add');
const isFor = ref(null);
const deviceType = ref('Desktop');
const layoutType = ref('Add');
const formControlList = ref([]);
const checkboxdata1 = ref([]);
const customFields = ref(null);
const formData = ref([]);
const fieldData = ref({});
const formSchemaObject = [];
const isLoading = ref(false);
const createSchema = ref(createYupSchema);
const handleSubmit1 = ref(null);
const errors1 = ref(null);
const meta1 = ref(null);
const getUserInfo = () => {
userId.value = localStorage.getItem("userId");
companyId.value = localStorage.getItem("companyId");
}
const getCustomFieldsData = () => {
commonService.value.getCustomFieldsData(primaryKey.value, moduleCode.value, subModuleCode.value, otherData.value, refId.value, displayCode.value, companyId.value, userId.value,
isFor.value, deviceType.value, layoutType.value)
.then(response => {
customFields.value = response.data.data;
customFields.value.forEach(t => {
let groupCheck = formControlList.value.filter(y => y.group_id == t.group_id);
if (t.dt_code == 'radio') {
t.listoptions = JSON.parse(t.listoptions);
}
if (t.dt_code == 'checkbox') {
t.listoptions = JSON.parse(t.listoptions);
let checkdata = {
controlname: t.form_controlName
};
checkboxdata1.value.push(checkdata);
}
if (groupCheck == null || groupCheck.length == 0) {
let obj = {
group_id: t.group_id,
group_name: t.group_name,
group_display_name: t.group_display_name,
InnerData: customFields.value.filter(x => x.group_id == t.group_id)
}
formControlList.value.push(obj);
}
});
//const group = {};
customFields.value.forEach(cnt => {
let val = null;
if (cnt.actual_data_type == 'bit') {
val = cnt.value == 1 ? true : false;
}
// else if (cnt.dt_code == 'datetime') {
// val = (cnt.value == '' ? null : convertdatetime.transform(cnt.value, null)); // to convert to local time
// }
// else if (cnt.dt_code == 'date') {
// val = (cnt.value == '' ? null : convertdatetime.transform(cnt.value, 'Date')); // to convert to local time
// }
else {
val = (cnt.value == '' ? null : cnt.value);
}
checkboxdata1.value.forEach((item) => { if (cnt.form_controlName == item.controlname) { item.controlvalues = cnt.value; } });//for checkboxes on form
if (cnt.actual_data_type == 'checkbox') {
try {
checkboxdata1.value.forEach((item) => { // // console.log(item.controlname, item.controlvalues);
this.form.get(item.controlname).setValue(item.controlvalues.split(','));
});
}
catch (err) { }
}
fieldData.value[cnt.form_controlName] = '';
formSchemaObject.push({
id: cnt.form_controlName,
label: cnt.display_name,
placeholder: cnt.display_name,
type: cnt.dt_code,
validationType: 'string',
value: '',
validations: [
{
type: "required",
params: ["this field is required"]
},
{
type: "min",
params: [5, "name cannot be less than 5 characters"]
},
{
type: "max",
params: [10, "name cannot be more than 10 characters"]
}
]
});
});
const { handleSubmit, errors, meta } = generateForm(formSchemaObject);
handleSubmit1.value = handleSubmit;
errors1.value = errors;
meta1.value = meta;
console.log("errors1", errors1)
})
}
const { handleSubmit, errors, meta } = useForm({
validationSchema: generateForm(),
});
const generateForm = (formArray) => {
const yepSchema = formArray.reduce(createSchema.value, {});
const schema = Yup.object().shape(yepSchema);
return schema;
}
const onSubmit = async () => {
var dataModel = new JsonData();
console.log('asdsad', fieldData.value);
dataModel.Id = primaryKey.value;
dataModel.ModuleCode = moduleCode.value;
dataModel.SubModuleCode = subModuleCode.value;
dataModel.CompanyId = companyId.value;
dataModel.UserId = userId.value;
dataModel.FormJsonData = JSON.stringify(fieldData.value);
console.log('dataModel', dataModel);
await assetCategoryService.value.addEditAssetCategory(dataModel).then(response => {
console.log(response);
// if (response.data.statusCode == 200) {
// toaster.success(response.data.responseMessage);
// setTimeout(() => { isLoading.value = false; router.push({ path: '/managelayoutList' }); }, 500);
// }
// else {
// isLoading.value = false;
// toaster.error(response.data.responseMessage);
// }
}).catch(error => { isLoading.value = false; console.log('error', error.response) })
}
onBeforeMount(() => {
getUserInfo();
getCustomFieldsData();
});
onMounted(() => {
});
return {
formControlList, fieldData, formSchemaObject, errors1,
onSubmit
}
}
}
export class JsonData {
Id
FormJsonData
ModuleCode
SubModuleCode
CompanyId
UserId
constructor() {
this.Id = null;
this.FormJsonData = "";
this.ModuleCode = "";
this.SubModuleCode = "";
this.CompanyId = "";
this.UserId = "";
}
}
export class Group {
id
group_id
group_name
group_display_name
group_layout_type
layout_type
table_name
is_inserted
is_updated
display_order
visibility_condition
visibility_condition_label
default_value
controls
constructor(
id,
group_id,
group_name,
group_display_name,
group_layout_type,
layout_type,
table_name,
is_inserted,
is_updated,
display_order,
visibility_condition,
visibility_condition_label,
default_value,
controls
) {
this.id = id,
this.group_id = group_id,
this.group_name = group_name,
this.group_display_name = group_display_name,
this.group_layout_type = group_layout_type,
this.layout_type = layout_type,
this.table_name = table_name,
this.is_inserted = is_inserted,
this.is_updated = is_updated,
this.display_order = display_order,
this.visibility_condition = visibility_condition,
this.visibility_condition_label = visibility_condition_label,
this.default_value = default_value,
this.controls = controls
}
}
</script>
<style scoped></style>