ecp_dform_app 2.1.7+1 copy "ecp_dform_app: ^2.1.7+1" to clipboard
ecp_dform_app: ^2.1.7+1 copied to clipboard

动态表单

ecp_dform_app #

ecp_dform_app 是一个自动生成渲染表单组件的组件库,通过渲染特定规则Json字符串渲染样式,特定规则数据Json字符串渲染数据;目前组件支持渲染如下组件:

此库专为内部项目需求设计,若不符合您的使用场景,敬请谅解。

  • 输入框(Input)
  • 数字输入框(InputNumber)
  • 多行输入框 (Input.TextArea)
  • 备注(remark)
  • 时间选择 (TimePicker)
  • 日期选择 (DatePicker)
  • 组件布局(FormLayout)
  • 单选框 (Radio.Group)
  • 组件网格布局(FormGrid)
  • 组件网格子布局 (FormGrid.GridColumn)
  • 上传文件 (YiFileUpload)

对应默认组件名称如下:

  • input/InputNumber ->TextEditorField
  • datePicker ->DatePickerField
  • timePicker ->TimePickerField
  • textArea/textArea ->TextAreaField
  • radioGroup ->radioPicker
  • formGrid ->formGrid
  • gridColumn ->gridColumn
  • fileUpload -> UploadFileField

简单使用 #

  • 准备组件样式Json字符串(本地或远程网络)
{
  "schema": {
    "x-designable-id": "momamuigso7",
    "type": "object",
    "properties": {
      "Input1": {
        "x-component": "Input",
        "x-decorator": "FormItem",
        "x-designable-id": "q5wn6s6b8a0",
        "x-display": "visible",
        "x-decorator-props": {},
        "name": "Input1",
        "x-pattern": "readOnly",
        "x-validator": {},
        "x-component-props": {
          "required": false
        },
        "type": "string",
        "title": "输入1",
        "x-index": 0
      },
      "Input2": {
        "x-component": "Input",
        "x-decorator": "FormItem",
        "x-designable-id": "cse7oco9skb",
        "x-display": "visible",
        "x-decorator-props": {
        },
        "name": "Input2",
        "x-pattern": "editable",
        "x-validator": {
        },
        "x-component-props": {
          "required": true
        },
        "type": "string",
        "title": "输入2",
        "x-index": 1
      },
      "ewgsrvgtu25": {
        "x-component": "Input",
        "x-decorator": "FormItem",
        "x-designable-id": "ewgsrvgtu25",
        "x-display": "visible",
        "x-decorator-props": {},
        "x-pattern": "readOnly",
        "x-validator": {},
        "x-component-props": {
          "required": true
        },
        "type": "string",
        "title": "输入3",
        "x-index": 2
      }
    }
  }
}
  • 准备对应组件初始化数据(本地或远程网络)
{
  "Input1": "3131",
  "Input2": "1414",
  "ewgsrvgtu25": "414141"
}
  • 渲染
DynamicForm(
  jsonSchema: _jsonSchema, ///样式Json字符串
  dataSchema: _data, ///数据Json字符串
  controller: controller, ///控制器
)

属性说明 #

DynamicForm #

最终动态表单渲染组件,负责解析和渲染工作,默认渲染样式为ListView,其中包含可传入参数如下:

  • items:静态表单数据,内部包含组件样式及数据,适用于静态渲染
  • controller:动态表单组件控制器,负责处理数据
  • factory:组件样式适配器,默认为DefaultMapperFactory
  • jsonSchema:组件样式Json字符串
  • dataSchema:组件数据字符串
  • parse:解析器,负责将jsonSchema以及dataSchema解析为List
  • physics:滑动类型,因为表单可能内嵌于其他滑动组件,防止动态表单渲染组件内ListView与外部组件冲突,建议设置成NeverScrollableScrollPhysics
  • shrinkWrap:防止滑动嵌套时,内部ListView组件渲染不全
  • permissions:控制表单组件显示、隐藏以及编辑功能

DynamicFormController #

动态表单控制器,用来控制整体表单数据行为,提供如下方法:

  • reset:重置所有表单值
  • save:保存当前表单值
  • validate:校验表单组件是否合法
  • submit:提交表单信息,首先通过[validate]方法校验是否表单是否合法,其次调用[save]方法保存表单数据至[FormSharedWidget]的[savedResult]中,最后调用[DynamicForm]的onSaved方法

DynamicFormConfig #

DynamicFormConfig保存了动态表单全局表单适配器以及解析器信息,可在应用初始化时替换

  • factory:表单适配器,默认DefaultMapperFactory
  • parse:表单解析器,默认_defaultParse

默认表单组件 #

动态表单内设置了默认表单组件,可根据需求继承/重写表单样式。

TextEditorField #

Screenshot_20221124-110337.png #

TextPickField #

Screenshot_20221124-110542.png

RadioPickerField #

Screenshot_20221124-110814.png

DatePickerField #

Screenshot_20221124-110819.png

TimePickerField #

Screenshot_20221124-110824.png

UploadFileField(Card) #

Screenshot_20221124-112109.png

UploadFileField(List) #

Screenshot_20221124-112116.png #

自定义表单组件 #

若默认组件不满足需求,那么我们就需要自定义表单组件,自定义组件的步骤如下:

  1. 继承DynamicFieldState,重写content或者build方法,必要时重写didChange方法,更改组件数据
class DynamicTextFieldState<T> extends DynamicFieldState<T> {
  @protected
  late TextEditingController controller;

  DynamicTextField<T> get _widget => widget as DynamicTextField<T>;

  @override
  Widget content() => TextField(
        controller: controller,
        keyboardType: _widget.inputType,
        inputFormatters: _widget.inputFormatters,
        style: _widget.contentStyle ?? context.bodyMediumStyle,
        textAlign: _widget.contentAlign ?? TextAlign.end,
        readOnly: _widget.readOnly ?? formItem.readOnly,
        enabled: !(_widget.readOnly ?? formItem.readOnly),
        onChanged: (newValue) {
          if (value is String?) {
            didChange(newValue as T);
          }
        },
        maxLines: _widget.maxLines,
        minLines: _widget.minLines,
        maxLength: _widget.maxLength,
        decoration: _widget.contentDecoration ??
            InputDecoration(
              isCollapsed: true,
              border: InputBorder.none,
              contentPadding:
                  _widget.contentPadding ?? EdgeInsets.only(left: 8.w),
              hintText: _widget.hint,
              hintStyle: _widget.hintStyle,
            ),
      );
  
  ...

  @override
  void didChange(T? value) {
    _updateText(value);
    super.didChange(value);
  }
}
  1. 继承DynamicField,重写createState方法,返回1步骤中继承DynamicFieldState的类型
///带文字输入框基础组件
///
///@author lzj
///
///@since 2022/8/8 14:10
class DynamicTextField<T> extends DynamicField<T> {
  ///忽略属性代码
  ...

  DynamicTextField({
    super.key,
   ...
  }) :super();

  @override
  DynamicTextFieldState<T> createState() => DynamicTextFieldState<T>();
}