1. Renderings
2. Parameter configuration
1. Code example
<t-antd-form :ref-obj.sync="formOpts.ref" :formOpts="formOpts" :widthSize="1" :labelCol="{ span:2}" :wrapperCol="{ span:22}" @handleEvent="handleEvent" />
2. Configuration parameters inherit all properties of FormModel
Parameter | Description | Type | Default value | |
---|---|---|---|---|
refObj | form form validation rule method (you can refer to validate in the antd FormModel form method) | obj | – | |
className | Custom class name | String | – | |
layout | Change the layout of the form item label and input box (default: horizontal) /vertical | String | ‘horizontal’ | |
widthSize | Display per line Several input items (default two) Maximum value 4 | Number | 2 | |
isTrim | Whether to enable clearing of leading and trailing spaces globally (comp is a-input and type is not equal to ‘password’) | Boolean | true | |
formOpts | Form configuration items | Object | {} | |
-listTypeInfo | Drop-down selection data source (type:’select’ is valid) | td> | Object | {} |
-fieldList | form form list | Array | [] | |
——isHideItem | An item is not displayed | Boolean | false | |
——slotName | Customize an input box of a form | slot | – | |
——childSlotName | Customize the slot of a certain drop-down selection subcomponent of the form (a-select-option) | slot | – | |
——comp | Form each component is an input box or drop-down selection, etc. (You can use third-party UI such as a-select/a-input or you can use custom components) | String | – | |
——formItemBind | Form each An attribute (inherits the Attributes of FormModelItem) | Object | {} | |
——bind | Each attribute of the form (inherits the Attributes of the third-party UI, such as in a-input allowClear clearing function) default clearing and drop-down filtering | Object | {} | |
——isTrim | Whether to clear the spaces before and after (comp is a-input and type is not equal to ‘password ‘) | Boolean | false | |
——type | Form form each item type | String | – | |
——widthSize | The proportion of an item in the form form (if it occupies a whole row, set 1) | Number | 2 | |
——width | The actual proportion of a certain item in the form form Width | String | 100% | |
——arrLabel | type=select-arr, the Chinese displayed in each drop-down | String | ‘label’ | |
——arrKey | When type=select-arr, each drop-down display shows the Chinese number transmitted to the background | String | ‘value’ | |
——label | For each item title | String | – | |
——labelRender | Customize a certain item title | function | – | |
——value | Parameters passed to the background for each form form item | String | – | |
——rules | Form validation rules for each input box | Object/Array | – | |
——list | Drop-down selection data source (only valid for type:’select’) | String | – | |
——event | Event mark of each form item (handleEvent event) | String | – | |
——eventHandle | Inherit the event of comp component (return Two parameters, the first comes with it, the second formOpts) | Object | – | |
——isSelfCom | Whether to use its own encapsulated components (TAntdSelect, etc. – including drop-down box) | Boolean | false | |
-formData | Form submission data (corresponding to the value of each item in fieldList) | Object | – | |
-labelCol | label Width ({ span:2}) | Object | {span:2} | |
-wrapperCol | Input box width | Object | {span:22} | |
-rules | Rule (can be configured according to AntdUI FormModel–corresponding to the value of formData) | Object/Array | – | |
-operatorList | Operation button list | Array | – |
3. events inherit all events of FormModel
Event name | Description | Return value |
---|---|---|
handleEvent | A single query condition triggers an event | Type/query condition input value in fieldList/event value in fieldList |
4. Methods
Event name | Description | Parameters |
---|---|---|
resetFields | Reset form | – |
clearValidate | Clear Validate Check | – |
5. Some properties provided by Ant-Design-Vue FormModel/FormModelItem can be used directly without any other configuration
3. Source code
<template> <FormModel ref="form" class="t_antd_form" :class="className" :model="formOpts.formData" :rules="formOpts.rules" :layout="formOpts.layout||'horizontal'" v-bind="formAttr" v-on="$listeners" > <template v-for="(item, index) in fieldList"> <FormModelItem v-if="!item.isHideItem" :key="index" :prop="item.value" :label="item.label" :class="[item.className]" :rules="item.rules" :style="getChildWidth(item)" v-bind="{...item.formItemBind}" > <!-- Custom label --> <template #label v-if="item.labelRender"> <render-comp :createElementFunc="item.labelRender" /> </template> <!-- Custom input box slot --> <template v-if="item.slotName"> <slot :name="item.slotName"></slot> </template> <!-- Text display value --> <template v-if="item.textShow"> <span>{<!-- -->{item.textValue||formOpts.formData[item.value]}}</span> </template> <template v-if="item.isSelfCom"> <component :is="item.comp" v-model="formOpts.formData[item.value]" :placeholder="item.placeholder||getPlaceholder(item)" v-bind="{allowClear:true,showSearch:true,...item.bind}" :style="{width: item.width||'100%'}" v-on="cEvent(item)" /> </template> <component v-if="!item.slotName & amp; & amp;!item.textShow & amp; & amp;!item.isSelfCom" :is="item.comp" v-model="formOpts.formData[item.value]" :type="item.type||item.bind.type" :mode="item.comp.includes('picker')?(item.type||item.bind.type):''" :placeholder="item.placeholder||getPlaceholder(item)" @change="handleEvent(item.event, formOpts.formData[item.value],item)" v-bind="{allowClear:true,showSearch:true,...item.bind}" :style="{width: item.width||'100%'}" v-on="cEvent(item)" > <template #addonBefore v-if="item.addonBefore">{<!-- -->{ item.addonBefore }}</template> <template #addonAfter v-if="item.addonAfter">{<!-- -->{ item.addonAfter }}</template> <template v-if="item.childSlotName"> <slot :name="item.childSlotName"></slot> </template> <component v-else :is="compChildName(item)" v-for="(value, key, index) in selectListType(item)" :key="index" :disabled="value.disabled" :label="compChildLabel(item,value)" :value="compChildValue(item,value,key)" >{<!-- -->{compChildShowLabel(item,value)}}</component> </component> </FormModelItem> </template> <!-- button --> <div class="footer_btn"> <template v-if="formOpts.btnSlotName"> <slot :name="formOpts.btnSlotName"></slot> </template> <template v-if="!formOpts.btnSlotName & amp; & amp;formOpts.operatorList & amp; & amp;formOpts.operatorList.length>0"> <Button v-for="(val,index) in formOpts.operatorList" :key="index" @click="val.fun(val)" :type="val.type||'primary'" :icon="val.icon" :size="val.size || 'default'" :disabled="val.disabled" >{<!-- -->{ val.label }}</Button> </template> </div> </FormModel> </template> <script> import RenderComp from './render-comp.vue' import {<!-- --> FormModel, Button } from 'ant-design-vue' export default {<!-- --> name: 'TAntdForm', components: {<!-- --> RenderComp, FormModel, FormModelItem: FormModel.Item, Button }, props: {<!-- --> /** Form configuration item description * formData object form submission data * rules object verification rules * fieldList Array form rendering data * operatorList Array operation button list * listTypeInfo object drop-down option data */ formOpts: {<!-- --> type: Object, default: () => ({<!-- -->}) }, // Custom class name className: {<!-- --> type: String }, // Display several input items in one line; maximum value 4 widthSize: {<!-- --> type: Number, default: 2, validator: (value) => {<!-- --> return value <= 4 } }, //Whether clearing spaces before and after is enabled globally isTrim: {<!-- --> type: Boolean, default: true }, //ref refObj: {<!-- --> type: Object } }, data() {<!-- --> return {<!-- --> colSize: this.widthSize, fieldList: this.formOpts.fieldList } }, computed: {<!-- --> formAttr() {<!-- --> let attr = {<!-- -->} this.formOpts.layout === 'vertical' ? attr = {<!-- --> ...this.$attrs } : attr = {<!-- --> labelCol: {<!-- --> span: 2 }, wrapperCol: {<!-- --> span: 22 }, ...this.$attrs } return attr }, cEvent() {<!-- --> return ({<!-- --> eventHandle }, type) => {<!-- --> let event = {<!-- --> ...eventHandle } let changeEvent = {<!-- -->} Object.keys(event).forEach(v => {<!-- --> changeEvent[v] = (e, ids) => {<!-- --> if (type === 't-antd-select-table') {<!-- --> event[v] & amp; & amp; event[v](e, ids, arguments) } else {<!-- --> if ((typeof e === 'number' & amp; & amp; e === 0) || e) {<!-- --> event[v] & amp; & amp; event[v](e, this.formOpts, arguments) } else {<!-- --> event[v] & amp; & amp; event[v](this.formOpts, arguments) } } } }) return {<!-- --> ...changeEvent } } }, selectListType() {<!-- --> return ({<!-- --> list }) => {<!-- --> if (this.formOpts.listTypeInfo) {<!-- --> return this.formOpts.listTypeInfo[list] } else {<!-- --> return [] } } }, // Subcomponent name compChildName() {<!-- --> return ({<!-- --> type }) => {<!-- --> switch (type) {<!-- --> case 'checkbox': return 'a-checkbox' case 'radio': return 'a-radio' case 'select-arr': case 'select-obj': return 'a-select-option' } } }, //Sub-subcomponent label compChildLabel() {<!-- --> return ({<!-- --> type, arrLabel }, value) => {<!-- --> switch (type) {<!-- --> case 'radio': case 'checkbox': return value.value case 'select-arr': return value[arrLabel || 'label'] case 'select-obj': return value } } }, // child subcomponent value compChildValue() {<!-- --> return ({<!-- --> type, arrKey }, value, key) => {<!-- --> switch (type) {<!-- --> case 'radio': case 'checkbox': return value.value case 'select-arr': return value[arrKey || 'value'] case 'select-obj': return key } } }, // Sub-subcomponent text display compChildShowLabel() {<!-- --> return ({<!-- --> type, arrLabel }, value) => {<!-- --> switch (type) {<!-- --> case 'radio': case 'checkbox': return value.label case 'select-arr': return value[arrLabel || 'label'] case 'select-obj': return value } } } }, watch: {<!-- --> 'formOpts.formData': {<!-- --> handler(val) {<!-- --> // Return the form instance to the parent this.$emit('update:refObj', this.$refs.form) }, deep: true // deep monitoring }, widthSize(val) {<!-- --> if (val > 4) {<!-- --> this.$message.warning('widthSize value cannot be greater than 4!') this.colSize = 4 } else {<!-- --> this.colSize = val } } }, mounted() {<!-- --> // Return the form instance to the parent this.$emit('update:refObj', this.$refs.form) }, methods: {<!-- --> //Layout of label and input box getChildWidth(item) {<!-- --> if (this.formOpts.layout === 'vertical') {<!-- --> return `flex: 0 1 calc((${<!-- -->100 / (item.widthSize || this.colSize)}% - 10px));margin-right:10px;` } else {<!-- --> return `flex: 0 1 ${<!-- -->100 / (item.widthSize || this.colSize)}%;` } }, // Get the display of placeholder getPlaceholder(row) {<!-- --> let placeholder if (typeof row.comp === 'string' & amp; & amp; row.comp) {<!-- --> if (row.comp.includes('input')) {<!-- --> placeholder = row.label ? `Please enter ${<!-- -->row.label}` : `Please enter` } else if (row.comp.includes('select') || row.comp.includes('cascader')) {<!-- --> placeholder = row.label ? `Please select ${<!-- -->row.label}` : `Please select` } else if (!row.comp.includes('t-antd-date-picker')) {<!-- --> placeholder = row.label } } else {<!-- --> placeholder = row.label } return placeholder }, //Bound related events handleEvent(type, val, item) {<!-- --> // console.log('component', type, val, item) //Remove leading and trailing spaces if (this.isTrim & amp; & amp; !item.isTrim & amp; & amp; item.comp.includes('input') & amp; & amp; item.type !== 'password' & amp; & amp; item.type !== 'inputNumber') {<!-- --> this.formOpts.formData[item.value] = this.formOpts.formData[item.value].trim() } this.$emit('handleEvent', type, val) }, validate() {<!-- --> // selfValidate() {<!-- --> return new Promise((resolve, reject) => {<!-- --> this.$refs.form.validate(valid => {<!-- --> if (valid) {<!-- --> resolve({<!-- --> valid, formData: this.formOpts.formData }) } else {<!-- --> // eslint-disable-next-line prefer-promise-reject-errors reject({<!-- --> valid, formData: null }) } }) }) }, //Reset form resetFields() {<!-- --> return this.$refs.form.resetFields() }, // Clear verification clearValidate() {<!-- --> return this.$refs.form.clearValidate() } } } </script> <style lang="scss"> .t_antd_form {<!-- --> display: flex; flex-wrap: wrap; .ant-select, .ant-calendar-picker {<!-- --> width: 100%; } .footer_btn {<!-- --> display: flex; align-items: center; justify-content: center; margin-top: 5px; width: 100%; .ant-btn {<!-- --> margin-left: 10px; } .ant-btn:first-child {<!-- --> margin-left: 0; } } } </style>
4. Component address
gitHub component address
gitee code cloud component address
5. Related articles
Encapsulate basic component documents again based on ElementUi
Encapsulate basic component documents again based on ant-design-vue
vue3 + ts re-encapsulates basic component documents based on Element-plus