1. Renderings
Figure 1: Verification effect
2. Main code
Note:
1. The form and table are bound to the same data tableSource and it is a data (ElementUI requires an object package array)
2. The form uses name binding -> :name=”[index, ‘vlan_id’]”
3. Form-item always needs to add rules -> :rules=”rules.blur”
<a-form ref="tableFormRef" :model="tableSource" :label-col="{ style: { width: '10px' } }" :wrapper-col="{ span: 0 }" :rules ="rules"> <a-table class="ant-table-striped" bordered :dataSource="tableSource" :columns="tableColumns" :pagination="false" :scroll="{ x: 1260 }" :row-class-name="(_record, index) => (index % 2 === 1 ? 'table-striped' : null)"> <template #bodyCell="{ column, text, record, index }"> <template v-if="column.dataIndex == 'vlan_id'"> <a-form-item class="custom-form-item" label=" " :name="[index, 'vlan_id']" :rules="rules.blur"> <a-input style="width: 100%" v-model:value="record[column.dataIndex]"></a-input> </a-form-item> </template> </template> </a-table> </a-form>
1.template
<div class="bottom-box"> <div class="title-box"> <p class="order-title">Work order operations</p> <a-button style="margin: 0 0 10px 0px" type="primary" size="small" @click="handleRowAdd">Add row</a-button> </div> <div class="table-box"> <a-form ref="tableFormRef" :model="tableSource" :label-col="{ style: { width: '10px' } }" :wrapper-col="{ span: 0 }" :rules="rules "> <a-table class="ant-table-striped" bordered :dataSource="tableSource" :columns="tableColumns" :pagination="false" :scroll="{ x: 1260 }" :row-class-name="(_record, index) => (index % 2 === 1 ? 'table-striped' : null)"> <template #bodyCell="{ column, text, record, index }"> <template v-if="column.dataIndex == 'vlan_id'"> <a-form-item class="custom-form-item" label=" " :name="[index, 'vlan_id']" :rules="rules.blur"> <a-input style="width: 100%" v-model:value="record[column.dataIndex]"></a-input> </a-form-item> </template> <template v-else-if="column.dataIndex == 'cloud'"> <a-form-item class="custom-form-item" label=" " :name="[index, 'cloud']" :rules="rules.cloud"> <a-select style="width: 100%" v-model:value="record[column.dataIndex]" @change="hanlePlatformChange(index)"> <a-select-option v-for="item in platforms" :value="item.value" :key="item.value">{<!-- -->{ item.label }}</a- select-option> </a-select> </a-form-item> </template> <template v-else-if="column.dataIndex == 'related_pool'"> <a-form-item class="custom-form-item" label=" " :name="[index, 'related_pool']" :rules="rules.relatedPool"> <a-select style="width: 100%" v-model:value="record[column.dataIndex]"> <a-select-option v-for="item in platform[index].children" :value="item.value" :key="item.value">{<!-- -->{ item.label } }</a-select-option> </a-select> </a-form-item> </template> <template v-else-if="column.dataIndex == 'allocated' || column.dataIndex == 'purpose' || column.dataIndex == 'vlan_domain'"> <a-form-item class="custom-form-item" label=" " :name="[index, column.dataIndex]" :rules="rules.change"> <a-select style="width: 100%" v-model:value="record[column.dataIndex]"> <a-select-option v-for="item in column.list" :value="item.value" :key="item.value">{<!-- -->{ item.label }}</ a-select-option> </a-select> </a-form-item> </template> <template v-else-if="column.dataIndex == 'operation'"> <a-button style="margin: 0 5px" type="primary" size="small" @click="handleRowDel(index)" danger>Delete</a-button> </template> <template v-else> <a-input style="width: 100%" v-model:value="record[column.dataIndex]"></a-input> </template> </template> </a-table> </a-form> </div> <div class="btn-box"> <a-button v-if="sendFail" style="margin: 0 5px" @click="handleCancleApply">Cancel application</a-button> <a-button style="margin: 0 5px" type="primary" @click="handleSubmit">Submit</a-button> </div> </div>
2.script
<script setup> import { h, reactive, ref } from 'vue'; // Route jump import { useRouter } from 'vue-router'; const { currentRoute } = useRouter(); const router = useRouter(); const tableFormRef = ref(); // form tag /** * * Tabular data */ let tableSource = ref([]); //Verification rules const rules = { blur: [{ required: true, message: 'Please enter', trigger: 'blur' }], change: [{ required: true, message: 'Please select', trigger: 'change' }], cloud: [{ required: true, message: 'Please select the platform', trigger: 'change' }], relatedPool: [{ required: true, message: 'Please select a hardware resource pool', trigger: 'change' }] }; // submit application const handleSubmit = () => { let params = {}; if (tableSource.value.length == 0) { return message.error('The work order cannot be empty!'); } // form verification method tableFormRef.value.validate().then(() => { const tableSourceParams = JSON.parse(JSON.stringify(tableSource.value)); params = { ...formState, // other parameters status: 1, deviceLists: tableSourceParams }; //Interface submitOrder(params).then(res => { if (res.code == 8200) { cancelId.value = res.data.id; if (res.data.status == 3) { message.success('The secondary VLAN address was successfully added to the network!'); router.push({ path: '/network-access/vlan' }); } else if (res.data.status == 2) { message.error(failTip(res.data.errorMessage)); sendFail.value = true; // if (route.query.id) { // echoDate(); // } } } }); }); }; </script>