@icreate/ics-basic-form-builder
v0.0.29
Published
表单设计器
Downloads
15
Maintainers
Keywords
Readme
@[toc] 版本更新说明
- [ 0.0.29] 引入新的地址组件
- [ 0.0.28-beta.1] 更新ics-ui/ics-icon版本
- [ 0.0.28-beta.1] multi-column-select支持多选以及自定义搜索条件customFilter(结合数据tbodyOptions的data属性)
- [ 0.0.28-beta.0] 1.提供按钮点击时触发的方法buttonClickRender 2.地址组件支持添加同步按钮isShowButton,点击按钮触发方法syncAddress 3.栅格列支持设置padding
- [ 0.0.28] 1.地址组件更新(增加level/返回数据为对象) 2.基础字段支持重复拖入repeatFlag
- [ 0.0.27-beta.6] 修复:checkbox报错
- [ 0.0.27-beta.4] 修复:combogrid的label报错
- [ 0.0.27-beta.3] 修复:formData数据实时回显
- [ 0.0.27-beta.2] 修复:打包引入地址组件
- [ 0.0.27-beta.1] 1.地址级联组件(业务组件) area-cascader 2.新模板/ace-builds放入ics-ui
- [ 0.0.27] 1.label添加tooltip (字段labelTooltipContent/labelTooltipPlacement) 2.添加multi-column-select(select自定义模板:多列select)
- [ 0.0.26-beta.0] 修复栅格组件的自适应宽度问题
- [ 0.0.25 ] 1.可隐藏保存模板按钮saveFormTemplate:false,提供了自己保存的方法customSaveTemplate 2.栅格垂直方向对齐
- [ 0.0.24 ] 随ics-ui更新版本
- [ 0.0.23 ] 计数器默认值问题
- [ 0.0.22 ] 1.自定义组件的name值改为'自定义组件的类型(type) + Widget' 2.属性collapseTags:select多选时是否将选中值按文字的形式展示 - 3.组件设置增加了标签行高 4.表单设置:静态字段增加了左侧标识
- [ 0.0.21 ] 1.input:placeholder 2.组件设置:组件大小 3.表单设置:设置标签颜色labelColor以及标签字体大小labelFontSize 4.子表单
- [ 0.0.20 ] 支持引入自定义组件
- [ 0.0.19 ] input组件只读属性的样式,设置属性 readOnlyNoBorder
说明
这是一个表单设计器
安装
npm i @icreate/ics-basic-form-builder # 安装包
在vue使用
- 在vue项目的main.js中引入
import VForm from '@icreate/ics-basic-form-builder' //引入VForm库
import '@icreate/ics-basic-form-builder/styles/form-builder.css' //引入VForm样式
import IcsUI from '@icreate/ics-ui' //引入ics-ui
import '@icreate/ics-ui/lib/ics-ui.css'
Vue.use(IcsUI) //全局注册ics-ui
Vue.use(VForm) //全局注册VForm(同时注册了v-form-designer和v-form-render组件)
- 在Vue模板中使用表单设计器组件
<v-form-designer
ref="vfDesignerRef"
:designer-config="designerConfig"
:basicFieldsTransfer="basicFieldsTransfer"
:formJson="formJson"
:formTemplateJson="formTemplateJson"
@saveFormTemplateHandler="saveFormTemplateHandler"
:customComponentObj="customComponentObj"
></v-form-designer>
- 在Vue模板中使用表单渲染器组件
<v-form-render
ref="vFormRef"
:form-json="formJson"
:form-data="formData"
:option-data="optionData"
@appendButtonClick="appendButtonClickHandler"
@formChange="handleFormChange"
@buttonClickRender="buttonClickHandler"
@syncAddress="syncAddressHandler"
:customComponentObj="customComponentObj"
>
</v-form-render>
<ics-button type="primary" @click="submitForm">Submit</ics-button>
- 引入自定义组件(可选)
import customCom from "./customCom.vue"; //自定义组件的格式,请参考最后的示例
数据格式:
v-form-designer 表单设计器
designerConfig :表单设计器配置 (必传) basicFieldsTransfer : 基础字段组件(必传) formJson: 显示上次编辑的设计器页面 (选传) formTemplateJson :显示保存的模板 (选传) saveFormTemplateHandler :保存模板后的回调函数,可以获取到模板的json数据 customComponentObj: 自定义组件的对象格式
v-form-render 表单渲染器 formJson:需要渲染的表单的json数据(从设计器复制json数据)(必传) formData:需要渲染的表单数据(选传) optionData:动态传入的选项数据(例如:多选框的选项)(选传) appendButtonClickHandler : 输入框后置按钮的回调函数(选传) handleFormChange: 表单数据改变时触发 submitForm: 可以获取到表单数据formData customComponentObj: 自定义组件的对象格式
export default {
data() {
return {
customComponentArr:[customCom], //自定义组件的数组
customComponentObj:{}, //将数组转成对象的格式 (写在created())
designerConfig: {
resetFormJson: false,
toolbarMaxWidth: 490,
saveFormTemplate: false, //隐藏保存模板
},
basicFieldsTransfer: [
{ //自定义组件
type: "customType", //自定义类型
repeatFlag: true, // 组件可重复
formItemFlag: true,
options: {
name: "customName", //name唯一值
label: "自定义组件", //label值
labelAlign: "", //label对齐方式
defaultValue: null, //默认值
labelWidth: null, //标签宽度
labelHidden: false, //标签是否隐藏
hidden: false, //是否隐藏
required: false, //是否必填
requiredHint: "", //必填提示
columnWidth: '200px', //在子表单中的组件列宽
optionItems: [ //选项(ics-radio/ics-checkbox/ics-select...)
{ label: "选项1", value: 1 },
{ label: "选项2", value: 2 },
],
},
},
{
type: "data-table", //数据表格
options: {
name: "dataTable",
label: "数据表格",
tableWidth: "100%", //表格宽度
tableHeight: "300px", //表格高度
showCheckBox: true, //是否显示复选框列
stripe: true, //是否斑马线
tableBorder: true, //是否带有边框
showActionButton: true, //显示操作按钮列
optionItems: {
thOptions: [
//表头
{
label: "日期",
value: "date",
width: "180",
},
{
label: "姓名",
value: "name",
width: "180",
},
{
label: "地址",
value: "address",
width: "",
},
],
tbodyOptions: [
{
id: "1",
date: "2016-05-02",
name: "张三",
address: "上海市普陀区金沙江路 1518 弄",
},
{
id: "2",
date: "2016-05-04",
name: "李四",
address: "上海市普陀区金沙江路 1517 弄",
},
{
id: "3",
date: "2016-05-01",
name: "王二麻子",
address: "上海市普陀区金沙江路 1519 弄",
},
], //表格内容
},
},
},
{
type: "input", //表单组件类型(必传)
options: {
label: "输入框", //组件label(必传)
name: "inputtext", //组件name(必传,而且必须是唯一值)
type: "text", //input 输入框的类型(可传)
defaultValue:"", //默认值(可传)
required: true, //是否必填(可传)
requiredHint:'', //必填提示(可传)
validation: "/^[\u4e00-\u9fa5]+$/", //组件的正则校验规则 (可传)
validationHint: "只能输入中文哦", //校验提示语(可传)
reverseValidation:'/[^\u4e00-\u9fa5]/g', //数据格式:正则取反+g (需要限制输入时,必传)
max:"" ,//限制输入的最大值 (限制输入是数字的情况)
readOnlyNoBorder: true, //只读时的样式 不要边框
labelTooltipContent:"标签文字提示内容", //标签文字提示内容
labelTooltipPlacement:"top" //标签文字提示位置
},
},
{
type: "input",
options: {
label: "输入框",
name: "inputpsw",
type: "password",
},
},
{
type: "textarea",
options: {
label: "文本域",
name: "textarea",
},
},
{
type: "radio",
options: {
name: "radio",
label: "单选项",
optionItems: [ //选项列表(必传)
{
label: "选项1",
value: "1",
},
{
label: "选项2",
value: "2",
},
],
},
},
{
type: "checkbox",
options: {
name: "checkbox",
label: "多选框",
max: 1, // 可被勾选的 checkbox 的最大数量
optionItems: [ //选项列表(必传)
{
label: "选项1",
value: "1",
},
{
label: "选项2",
value: "2",
},
{
label: "选项3",
value: "3",
},
],
},
},
{
type: "number",
options: {
name: "number",
label: "计数器",
min: 0, //最小值(可传)
max: 100000, //最大值(可传)
precision: 0, //精度(可传)
step: 1, //增减步长(可传)
},
},
{
type: "select",
options: {
name: "select",
label: "下拉框",
labelAndValue: true, // 获取选项数据的格式(例如:选中下拉框,是否需要获取label值,默认不获取)
collapseTags: true, //多选时是否将选中值按文字的形式展示 默认为fale
optionItems: [ //下拉列表(必传)
{
id:"", // 唯一key值 (如果value值不唯一,id必传)
label: "select 1",
value: 1,
},
{
label: "select 2",
value: 2,
},
{
label: "select 3",
value: 3,
},
],
},
},
{
type: "select-plus",
options: {
name: "select-plus",
label: "下拉框加强版",
optionItems: [
{
label: "select 1",
value: 1,
},
{
label: "select 2",
value: 2,
},
{
label: "select 3",
value: 3,
},
],
},
},
{
type: "multi-column-select",
options: {
name: "multi-column-select",
label: "多列select",
labelColumn: "name", //label绑定的列
valueColumn: "id", //value绑定的列
showHeader: true, //是否显示表头
labelAndValue: true, //返回值是对象(label和value)
customFilter: ['id', 'name'], //自定义搜索的字段
optionItems: {
thOptions: [
// 表头
{
label: "日期",
value: "date",
width: "100",
},
{
label: "姓名",
value: "name",
width: "100",
},
{
label: "地址",
value: "address",
width: "260",
},
],
tbodyOptions: [
{
id: "1",
date: "2016-05-02",
name: "张三",
address: "上海市普陀区金沙江路 1518 弄",
data: {
id: '1',
name: '张三'
}
},
{
id: "2",
date: "2016-05-04",
name: "李四",
address: "上海市普陀区金沙江路 1517 弄",
data: {
id: '2',
name: '李四'
}
},
{
id: "3",
date: "2016-05-01",
name: "王二麻子",
address: "上海市普陀区金沙江路 1519 弄",
data: {
id: '3',
name: '王二麻子'
}
},
], // 表格内容
},
},
},
{
type: "time",
options: {
name: "time",
label: "时间",
format: "HH:mm:ss", //时间格式(可传)
},
},
{
type: "time-range",
options: {
name: "time-range",
label: "时间范围",
format: "HH:mm:ss", //时间格式(可传)
},
},
{
type: "date",
options: {
name: "date",
label: "日期",
format: "yyyy-MM-dd", //日期显示格式(可传)
valueFormat: "yyyy-MM-dd", //日期对象格式(可传)
},
},
{
type: "date-range",
options: {
name: "date-range",
label: "日期范围",
format: "yyyy-MM-dd", //日期显示格式(可传)
valueFormat: "yyyy-MM-dd", //日期对象格式(可传)
},
},
{
type: "datetime",
options: {
name: "datetime",
label: "日期时间",
format: "yyyy-MM-dd HH:mm:ss", //日期显示格式(可传)
valueFormat: "yyyy-MM-dd HH:mm:ss", //日期对象格式(可传)
},
},
{
type: "switch",
options: {
name: "switch",
label: "开关",
},
},
{
type: "rate",
options: {
name: "rate",
label: "评分",
},
},
{
type: "button",
options: {
name: "button",
label: "按钮",
},
},
{
type: "cascader",
options: {
name: "cascader",
label: "级联选择",
optionItems: [ //级联选择选项(必传)
{
label: "select 1",
value: 1,
children: [{ label: "child 1", value: 11 }],
},
{ label: "select 2", value: 2 },
{ label: "select 3", value: 3 },
],
},
},
{
type: "combo-grid",
options: {
name: "comboGrid",
label: "组合网格",
labelColumn: "name", //name列对应label
valueColumn: "id", //id列对应value(选中列表,获取的值)
valueKey:"", //添加表格数据的唯一key值属性(不传,默认是valueColumn)
labelAndValue: true, //true: 绑定的值是对象(含label) 默认为false
customFilter: ["id", "name"], //自定义搜索字段
optionItems: { //选项值:表头字段+表格数据 (必传)
thOptions: [
//表头
{
label: "日期",
value: "date",
width: "180",
},
{
label: "姓名",
value: "name",
width: "180",
},
{
label: "地址",
value: "address",
width: "260",
},
],
tbodyOptions: [
//表格内容
{
id: "111111",
date: "2016-05-02",
name: "王小虎1",
address: "上海市普陀区金沙江路 1518 弄",
},
{
id: "111112",
date: "2016-05-04",
name: "王小虎2",
address: "上海市普陀区金沙江路 1517 弄",
},
{
id: "111113",
date: "2016-05-01",
name: "王小虎3",
address: "上海市普陀区金沙江路 1519 弄",
},
],
},
},
},
{
type: 'area-cascader', // 业务组件 地址级联选择器
options: {
name: 'area-cascader',
label: '地址级联',
level: 1,
isShowButton: true, //是否显示右侧按钮
syncAddressData: [ //右侧checkbox-group的数据
{ id: 'nativeAddress', name: '籍贯地址' },
{ id: 'residenceAddress', name: '户口地址' },
{ id: 'birthAddress', name: '出生地址' },
{ id: 'unitAddress', name: '单位地址' },
{ id: 'connectAddress', name: '联系人地址' },
{ id: 'currentAddress', name: '现住址' }
]
}
},
{
type: 'address-cascader', // 新地址级联
options: {
name: 'address-cascader',
label: '新地址组件',
level: 3,
isShowButton: true,
syncAddressData: [
{ id: 'nativeAddress', name: '籍贯地址' },
{ id: 'residenceAddress', name: '户口地址' },
{ id: 'birthAddress', name: '出生地址' },
{ id: 'unitAddress', name: '单位地址' },
{ id: 'connectAddress', name: '联系人地址' },
{ id: 'currentAddress', name: '现住址' }
]
}
}
],
formTemplateJson:
JSON.parse(localStorage.getItem("saveFormTemplateJson")) || null,
formJson: {
widgetList: [
{
type: "input",
options: {
labelAlign: "",
defaultValue: "",
placeholder: "",
columnWidth: "200px",
size: "",
labelWidth: null,
labelHidden: false,
readonly: false,
disabled: false,
hidden: false,
clearable: true,
showPassword: false,
required: true,
requiredHint: "",
validation: "/^[一-龥]+$/",
validationHint: "只能输入中文哦",
minLength: null,
maxLength: null,
showWordLimit: false,
appendButton: true,
appendButtonDisabled: false,
buttonIcon: "el-icon-search",
label: "用户名",
name: "username",
type: "text",
},
icon: "text-field",
formItemFlag: true,
id: "username",
},
{
type: "input",
options: {
labelAlign: "",
defaultValue: "",
placeholder: "",
columnWidth: "200px",
size: "",
labelWidth: null,
labelHidden: false,
readonly: false,
disabled: false,
hidden: false,
clearable: true,
showPassword: false,
required: false,
requiredHint: "",
validation: "",
validationHint: "",
minLength: null,
maxLength: null,
showWordLimit: false,
appendButton: false,
appendButtonDisabled: false,
buttonIcon: "el-icon-search",
label: "密码",
name: "password",
type: "password",
},
icon: "text-field",
formItemFlag: true,
id: "password",
},
{
type: "textarea",
options: {
labelAlign: "",
defaultValue: "",
placeholder: "",
columnWidth: "200px",
size: "",
labelWidth: null,
labelHidden: false,
readonly: false,
disabled: false,
hidden: false,
clearable: true,
showPassword: false,
required: false,
requiredHint: "",
validation: "",
validationHint: "",
minLength: null,
maxLength: null,
showWordLimit: false,
appendButton: false,
appendButtonDisabled: false,
buttonIcon: "el-icon-search",
label: "留言板",
name: "message",
rows: 3,
},
icon: "text-field",
formItemFlag: true,
id: "message",
},
],
formConfig: {
labelWidth: 80,
labelPosition: "left",
size: "",
labelAlign: "label-left-align",
labelColor:"", //label颜色
labelFontSize:"", //label字体大小
labelLineHeight: "", //标签行高
cssCode: "",
customClass: "",
functions: "",
layoutType: "PC",
modelName: "formData",
refName: "vForm",
rulesName: "rules",
onFormCreated: "",
onFormMounted: "",
onFormDataChange: "",
},
},
formData: {},
optionData: { //动态传入的选项数据
checkbox: [ //checkbox 是name名称
{
label: "动态选项1",
value: "1",
},
{
label: "动态选项2",
value: "2",
},
{
label: "动态选项3",
value: "3",
},
],
},
};
},
methods: {
submitForm() {
this.$refs.vFormRef
.getFormData()
.then((formData) => {
// Form Validation OK
alert(JSON.stringify(formData));
})
.catch((error) => {
// Form Validation failed
this.$message.error(error);
});
},
saveFormTemplateHandler(data) {
//保存模板json数据
localStorage.setItem("saveFormTemplateJson", data);
this.$message.success("模板保存成功");
},
appendButtonClickHandler(data) {
//输入框添加后置按钮,回调函数
console.log("appendButtonClickHandler=======", data.$data.fieldModel);
},
handleFormChange(
fieldName,
newValue,
oldValue,
formDataModel,
subFormName,
subFormRowIndex,
comboGridItem
) {
//fieldName name
//newValue 新值
//oldValue 旧值
//formDataModel 表单数据
//comboGridItem 组合网格组件,传过来的对象
console.log(this.$refs["vFormRef"].widgetRefList) //获取每个组件的属性方法
this.$refs["vFormRef"].widgetRefList["select"].setRequired(true); //设置select组件必填属性为true
this.$refs["vFormRef"].widgetRefList["select"].setValue("1"); //设置select组件值为1
this.$refs["vFormRef"].widgetRefList["input"].setWidgetOption("max",newValue) //设置input组件的最大值为newValue
this.$refs["vFormRef"].widgetRefList["comboGrid"].setValueNotEmitHandler(newValue); //给组合网格赋值(赋值不会触发handleFormChange) //改变组合网格选项,会触发
this.$refs["vFormRef"].widgetRefList["select"].$refs.fieldEditor.toggleMenu(); //select组件 自动展开下拉框
},
customSaveTemplate(){
//自己保存模板的方法
this.$refs.vfDesignerRef.$refs.toolbarRef.saveFormTemplate() //方法的返回值即是保存的数据
},
buttonClickHandler(){}
},
created(){
this.customComponentArr.map((item) => {
return (this.customComponentObj[item.name] = item);
});
}
}
自定义组件的格式(.vue文件):
<!-- template 按需编写, 示例如下 -->
<div>
<ics-switch
ref="fieldEditor"
v-model="fieldModelData.switchVal"
></ics-switch>
<ics-input
class="marginBottom"
ref="fieldEditor"
v-model="fieldModelData.inputVal"
placeholder="请输入内容"
clearable
show-password
/>
<ics-select v-model="fieldModelData.selectVal" placeholder="请选择">
<ics-option
v-for="item in field.options.optionItems"
:key="item.value"
:label="item.label"
:value="item.value"
>
</ics-option>
</ics-select>
</div>
</template>
export default {
name: "customTypeWidget", //自定义组件的类型(type) + 'Widget'
data() {
return {
fieldModelData: {
switchVal: false, //每个组件的绑定值(名称自定义),都放在fieldModelData里面
inputVal: "",
selectVal: "",
}
};
},
props: {
field: Object, //basicFieldsTransfer的自定义组件的数据
value: Object,
},
model: {
prop: "value",
event: "change",
}, // v-model
methods: {
},
watch: {
value: {
handler(val) {
if (val) {
this.fieldModelData = this.value;
}
},
deep: true,
immediate: true,
},
fieldModelData: {
handler(val) {
this.$emit("change", val);
},
deep: true,
},
},
};
<style scoped>
.marginBottom {
margin-bottom: 20px;
}
</style>