vue2的element自定义表单(支持数据联动和表单联动)
element
A Vue.js 2.0 UI Toolkit for Web
项目地址:https://gitcode.com/gh_mirrors/eleme/element
免费下载资源
·
1. 表单部分
- template
<template>
<el-form ref="ruleForm" :model="ruleForm" :rules="rules" label-width="120px"
@submit.native.prevent
class="demo-ruleForm">
<el-form-item
v-for="(item, index) in formColumns"
:key="index"
:label="item.label"
:prop="item.prop"
>
<el-select
v-if="item.type === 'select'"
v-model="ruleForm[item.prop]"
:disabled="item.disabled"
:placeholder="exportPlaceholder(item.placeholder, item)"
@change="selectChange(item)"
>
<el-option v-for="(each, i) in item.options" :key="i"
:label="each.label" :value="each.value" />
</el-select>
<el-radio-group v-if="item.type === 'radioGroup'" v-model="ruleForm[item.prop]">
<el-radio v-for="(each, i) in item.options" :key="i" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
<el-checkbox-group v-if="item.type === 'checkboxGroup'" v-model="ruleForm[item.prop]">
<el-checkbox v-for="(each, i) in item.options" :key="i" :label="item.value">{{ item.label }}</el-checkbox>
</el-checkbox-group>
<el-input-number v-else-if="item.type === 'inputNumber'"
v-model="ruleForm[item.prop]"
controls-position="right"
:disabled="item.disabled"
/>
<el-input
v-else-if="item.type === 'input.number'"
v-model.number="ruleForm[item.prop]"
:disabled="item.disabled"
:placeholder="exportPlaceholder(item.placeholder, item)"
/>
<template v-else-if="item.type === 'password'">
<el-input v-model="ruleForm[item.prop]" show-password type="password"
:disabled="item.disabled"
autocomplete="off"
:placeholder="exportPlaceholder(item.placeholder, item)"
/>
</template>
<el-input v-else-if="item.type === 'textarea'"
v-model="ruleForm[item.prop]" type="textarea"
:disabled="item.disabled"
:placeholder="exportPlaceholder(item.placeholder, item)" />
<el-input v-else v-model="ruleForm[item.prop]" :placeholder="exportPlaceholder(item.placeholder, item)" />
</el-form-item>
<el-form-item v-if="useSubmit || useCancel">
<el-button v-if="useSubmit" type="primary" @click="submitForm">保存</el-button>
<el-button v-if="useCancel" @click="cancelForm">关闭</el-button>
</el-form-item>
</el-form>
</template>
2.js
function isEmpty(val) {
return val === null || val === undefined || val === '';
}
function notEmpty(val) {
return val !== null && val !== undefined && val !== '';
}
export default {
props: {
useSubmit: {
type: Boolean,
default() {
return false;
}
},
useCancel: {
type: Boolean,
default() {
return false;
}
},
defaultData: {
type: Object,
default() {
return {};
}
},
formObj: {
type: Object,
default() {
return {};
}
},
formList: {
type: Array,
default() {
return [];
}
},
optionsObj: {
type: Object,
default() {
return {};
}
}
},
data() {
return {
formColumns: [],
ruleForm: {},
rules: {}
};
},
watch: {
defaultData() {
this.setForm(true);
}
},
created() {
this.initOptions();
this.setForm(true);
},
mounted() {
// this.setForm();
},
methods: {
notEmpty,
// 下拉框切换
selectChange(item) {
if (item) {
const { ruleForm } = this;
if (item.hasOwnProperty('map')) {
this.clearMapOtherFormItems(item.map, ruleForm[item.prop]);
this.setForm();
} else if (item.hasOwnProperty('affect')) {
const result = this.handleAffectValue(item.affect, item);
this.$emit('updateOptions', {
// updateList: [],
// cleanList: [],
...result,
formData: JSON.parse(JSON.stringify(ruleForm))
});
}
}
},
// 处理影响数据
handleAffectValue(affect, data) {
const updateList = [];
const cleanList = [];
let targetAffect = affect;
const { formColumns, ruleForm } = this;
formColumns.some(item => {
if (item && item.prop === targetAffect) {
let value = '';
value = notEmpty(item.defaultValue) ? item.defaultValue : (item.type === '' ? '' : '');
ruleForm[item.prop] = value;
if (affect === targetAffect) {
updateList.push({ source: data.prop, target: targetAffect });
} else {
cleanList.push(targetAffect);
}
if (notEmpty(item.affect)) {
targetAffect = item.affect;
} else {
return true;
}
}
});
return {
updateList, cleanList
};
},
// 初始化表单所需的选择数据地址,方便后续配置
initOptions() {
const { formObj, optionsObj } = this;
Object.keys(formObj).forEach(item => {
if (optionsObj.hasOwnProperty(item) && formObj[item].type === 'select') {
this.$set(formObj[item], 'options', optionsObj[item]);
}
});
},
// 设置表单
setForm(isInit) {
const { formList, formColumns, ruleForm, rules, defaultData } = this;
// 1.先配置表单所用参数
const list = [];
this.setFormColumns(formList, list, isInit ? defaultData : ruleForm, isInit);
formColumns.splice(0, formColumns.length, ...list);
const props = list.map(item => item.prop);
// 2.清除非表单所用参数的其他数据
Object.keys(ruleForm).forEach(item => {
if (props.indexOf(item) < 0) {
this.$delete(ruleForm, item);
this.$delete(rules, item);
}
});
// const data = JSON.parse(JSON.stringify(ruleForm));
// 3.再按参数生成表单各项参数
for (let index = 0; index < formColumns.length; index++) {
const item = formColumns[index];
const arr = formColumns;
// formColumns.forEach((item, index, arr) => {
let value = '';
if (isInit) {
if (notEmpty(defaultData[item.prop])) {
value = defaultData[item.prop];
}
}
if (isEmpty(value)) {
value = notEmpty(item.defaultValue) ? item.defaultValue : (item.type === 'checkboxGroup' ? [] : '');
}
if (!ruleForm.hasOwnProperty(item.prop) || isInit) {
this.$set(ruleForm, item.prop, value);
}
if (isInit && notEmpty(value)) {
if (item.map) {
const { map } = item;
if (map) {
Object.keys(map).some(each => {
if (each === value) {
const eachArr = map[value];
if (eachArr.length > 0) {
const eachAddArr = [];
eachArr.forEach(one => {
if (!formColumns.find(every => every.prop === one.prop)) {
eachAddArr.push(Object.assign({}, formObj[one.prop], JSON.parse(JSON.stringify(one))));
} else { /**/ }
});
arr.splice(index + 1, 0, ...eachAddArr);
} else { /**/ }
return true;
} else { /**/ }
});
} else { /**/ }
} else { /**/ }
if (item.affect) {
this.$emit('updateOptions', {
updateList: [{ source: item.prop, target: item.affect }],
cleanList: [],
formData: JSON.parse(JSON.stringify(ruleForm))
});
}
}
if (item.required && !rules.hasOwnProperty(item.prop)) {
const rule = [];
if (item.type === 'select') {
rule.push({ required: true, message: '请选择' + item.label, trigger: 'change' });
} else {
rule.push({ required: true, message: '请输入' + item.label, trigger: 'blur' });
}
if (item.rule && item.rule.length > 0) {
rule.push(...item.rule);
}
this.$set(rules, item.prop, rule);
}
}
// });
this.$nextTick(() => {
if (this.$refs['ruleForm']) {
this.$refs['ruleForm'].clearValidate();
}
});
},
// 用来设置表单所需参数,存在迭代情况
setFormColumns(list, resultList, data, isInit) {
const { formObj } = this;
list.forEach(item => {
const obj = Object.assign({}, formObj[item.prop], JSON.parse(JSON.stringify(item)));
resultList.push(obj);
if (item.hasOwnProperty('map')) {
const map = item.map;
if (obj.type === 'checkboxGroup') {
let arr = [];
if (data[obj.prop] && data[obj.prop].length > 0) {
arr = JSON.parse(JSON.stringify(data[obj.prop]));
} else if (obj.defaultValue && obj.defaultValue.length > 0 && isInit) {
arr = JSON.parse(JSON.stringify(obj.defaultValue));
}
const { optionsObj } = this;
if (optionsObj[item.prop] && optionsObj[item.prop].length > 0) {
const options = optionsObj[item.prop].map(item => item.value);
arr.sort((a, b) => options.indexOf(a) - options.indexOf(b));
}
arr.forEach(each => {
if (notEmpty(each)) {
const list = map[each];
if (list && list.length > 0) {
this.setFormColumns(list, resultList, data, isInit);
} else { /**/ }
} else { /**/ }
});
} else {
const key = isInit ? (notEmpty(data[item.prop]) ? data[item.prop] : item.defaultValue) : data[item.prop];
const arr = map[key];
if (arr && arr.length > 0) {
this.setFormColumns(arr, resultList, data, isInit);
} else { /**/ }
}
}
});
},
// 清理map内其它未匹配的表单数据
clearMapOtherFormItems(map, key) {
const { ruleForm, rules } = this;
Object.keys(map).forEach(item => {
if (key !== item) {
map[item].forEach(each => {
if (ruleForm.hasOwnProperty(each.prop)) {
this.$delete(ruleForm, each.prop);
this.$delete(rules, each.prop);
}
if (each.hasOwnProperty('map')) {
this.clearMapOtherFormItems(each.map, key);
}
});
}
});
},
// 关闭表单
cancelForm() {
this.$emit('closeForm', this.ruleForm);
},
// // 提交表单
submitForm() {
this.$refs['ruleForm'].validate((valid) => {
if (valid) {
this.$emit('submitForm', this.ruleForm);
} else {
console.log('error submit!!');
return false;
}
});
},
// 重置表单
resetForm(formName) {
this.$refs['ruleForm'].resetFields();
},
// 输出占位提示
exportPlaceholder(item) {
const isSelect = item.type === 'select' || item.type === 'radioGroup' || item.type === 'checkboxGroup';
return notEmpty(item.placeholder) ? item.placeholder : (`请${isSelect ? '选择' : '输入'}${item.label}`);
}
}
};
2.调用
1.template
<template>
<div>
<CustomForm
ref="customForm"
class="pf-form scroll-white"
:form-obj="formObj"
:form-list="formList"
:default-data="defaultData"
:options-obj="optionsObj"
@updateOptions="updateOptions"
@submitForm="submitForm"
/>
<div class="text-center pf-box-ctrl">
<el-button size="mini" type="primary" @click="submit">保存</el-button>
</div>
</div>
</template>
import CustomForm from '@/components/CustomForm/index';
export default {
components: {
CustomForm
},
data() {
return {
defaultData: {},
formObj: {
'id': { type: 'select', options: [], required: true },
'table': { type: 'select', options: [], required: true },
'keyType': { type: 'select', options: [], required: true },
'field': { type: 'input', required: true },
},
formList: [
{ label: '数据库', prop: 'id', affect: 'table' },
{ label: 'table', prop: 'table' },
{ label: 'Key类型', prop: 'keyType', map: {
'HASH': [
{ label: 'Field', prop: 'field' }
],
'STRING': []
}}
],
optionsObj: {
id: [],
table: [],
keyType: [
{
'value': 'HASH',
'label': 'HASH'
},
{
'value': 'STRING',
'label': 'STRING'
}
]
}
};
},
created() {
// 1.设置默认数据,也可以直接在defaultData内置数据,设置默认数据主要是服务接口下发的数据
// this.$set(this, 'defaultData', JSON.parse(JSON.stringify(this.taskDetailSourceData)));
// 2.初始化时设置所需的选项数据,未必需要
// this.getIds();
},
methods: {
// 自组件触发,用于更新表单所需选项
updateOptions(data) {
const { updateList, cleanList, formData } = data;
const { optionsObj } = this;
console.log(data);
updateList.forEach(item => {
if (item.target === 'table') {
this.getTables(formData[item.source]);
}
});
cleanList.forEach(item => {
optionsObj[item].splice(0, optionsObj[item].length);
});
},
getTables(value) {
getTables({ id: value }).then(res => {
let result = res && res.data && res.data.length > 0 ? res.data : [];
result = result.map(item => {
return {
label: item,
value: item
};
});
this.optionsObj.table.splice(0, this.optionsObj.table.length, ...result);
}).catch(e => {});
},
getIds() {
getIds().then(res => {
if (res && res.data && res.data.length > 0) {
this.optionsObj.id.push(...res.data.map(item => {
return {
label: item.name,
value: item.id
};
}));
}
}).catch(e => {});
},
submitForm(data) {
this.$emit('submitData', { type: 'input', data });
},
submit() {
// 调子组件方法实现
this.$refs['customForm'].submitForm();
}
}
};
GitHub 加速计划 / eleme / element
54.06 K
14.63 K
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:3 个月前 )
c345bb45
7 个月前
a07f3a59
* Update transition.md
* Update table.md
* Update transition.md
* Update table.md
* Update transition.md
* Update table.md
* Update table.md
* Update transition.md
* Update popover.md 7 个月前
更多推荐
已为社区贡献12条内容
所有评论(0)