Flutter自动生成表单插件json_gen_form的使用

发布于 1周前 作者 bupafengyu 来自 Flutter

Flutter自动生成表单插件json_gen_form的使用

JSON_GEN_FORM

使用JSON生成Flutter表单,支持多种内置表单控件、验证、自定义布局、自定义样式以及无限嵌套的表单分组。

特性

  • 使用JSON渲染表单
  • 表单验证
  • 自定义表单样式
  • 自定义布局(行、列)
  • 无限表单分组和嵌套
  • 可以通过方法修改整个表单值或单独的表单控件值
  • 支持的表单控件:
    • 文本框
    • 密码框
    • 多行文本框
    • 数字输入框
    • 单选按钮
    • 复选框
    • 下拉选择框
    • 开关
    • 多媒体上传
    • 日期选择器
    • 时间选择器
    • 日期时间选择器

使用

import 'package:flutter/material.dart';
import 'package:json_gen_form/json_gen_form.dart';

void main() {
  runApp(const MainApp());
}

class MainApp extends StatefulWidget {
  const MainApp({super.key});

  @override
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {
  final GlobalKey _key = GlobalKey<JsonGenFormState>();
  final List<dynamic> _data = [
    {
      "type": "group",
      "label": "分组1",
      "field": "group1",
      "children": [
        {
          "type": "row",
          "gutter": 10,
          "children": [
            {
              "type": "col",
              "child": {"type": "text", "field": "name", "label": "组名1"}
            },
            {
              "type": "col",
              "child": {"type": "number", "field": "num", "label": "人数"}
            }
          ]
        },
        {"type": "text", "field": "manage", "label": "管理员"}
      ]
    },
    {
      "type": "text",
      "field": "name",
      "label": "姓名",
      "value": "隔壁老王",
      "readonly": true,
      "placeholder": "请输入姓名",
      "rules": [
        {"required": true, "message": "请输入姓名"}
      ]
    },
    {
      "type": "password",
      "field": "password",
      "label": "密码",
      "value": null,
      "placeholder": "请输入密码",
      "rules": [
        {"required": true, "message": "请输入密码"},
        {
          "pattern": "^[a-zA-Z0-9_-]{6,16}$",
          "message": "密码必须为6-16位字母、数字、下划线、减号"
        }
      ]
    },
    {
      "type": "textarea",
      "field": "remark",
      "label": "自我介绍",
      "value": null,
      "placeholder": "请简单介绍一下你自己",
      "rules": []
    },
    {
      "type": "number",
      "field": "age",
      "label": "年龄",
      "value": null,
      "placeholder": "请输入年龄",
      "rules": [
        {"required": true, "message": "请输入年龄"},
        {"min": 18, "message": "年龄必须大于18岁"}
      ]
    },
    {
      "type": "select",
      "field": "province",
      "label": "省份",
      "value": 1,
      "placeholder": "请选择省份",
      "options": [
        {"label": "山西", "value": 1},
        {"label": "陕西", "value": 2},
        {"label": "山东", "value": 3}
      ]
    },
    {
      "type": "cascade",
      "field": "city",
      "label": "城市",
      "value": null,
      "placeholder": "请选择城市",
      "options": [
        {
          "label": "山西",
          "value": 1,
          "children": [
            {
              "label": "太原",
              "value": 11,
              "children": [
                {"label": "小店区", "value": 111},
                {"label": "迎泽区", "value": 112}
              ]
            },
            {"label": "吕梁", "value": 12},
            {"label": "大同", "value": 13}
          ]
        },
        {
          "label": "陕西",
          "value": 2,
          "children": [
            {"label": "西安", "value": 21},
            {"label": "咸阳", "value": 22}
          ]
        }
      ]
    },
    {
      "type": "date",
      "field": "birthday",
      "label": "生日",
      "value": null,
      "placeholder": "请选择生日"
    },
    {
      "type": "radio",
      "field": "sex",
      "label": "性别",
      "value": null,
      "options": [
        {"label": "男", "value": 1},
        {"label": "女", "value": 2},
        {"label": "保密", "value": 0}
      ]
    },
    {
      "type": "checkbox",
      "field": "hobby",
      "label": "爱好",
      "value": [],
      // "direction": "vertical",
      "options": [
        {"label": "篮球", "value": "basketball"},
        {"label": "足球", "value": "football"},
        {"label": "羽毛球", "value": "badminton"}
      ],
      "rules": [
        {"required": true, "message": "请选择爱好"}
      ]
    },
    {
      "type": "switch",
      "field": "agree",
      "label": "同意协议",
      "value": null,
      "rules": [
        {"required": true, "message": "请同意协议"}
      ]
    },
    {
      "type": "media",
      "field": "media",
      "label": "上传照片视频",
      "value": null,
      "rules": null,
      "multiple": true
    }
  ];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        brightness: Brightness.light,
        useMaterial3: true,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('json gen form'),
        ),
        body: SafeArea(
          child: SingleChildScrollView(
            physics: const BouncingScrollPhysics(),
            padding: const EdgeInsets.symmetric(
              horizontal: 20.0,
              vertical: 20.0,
            ),
            child: Column(
              children: [
                JsonGenForm(
                  key: _key,
                  config: _data,
                  decoration: JsonGenFormDecoration(
                    // groupLabelWrap: (Widget child, dynamic data) {
                    //   return Container(
                    //     margin: const EdgeInsets.only(bottom: 5),
                    //     child: child,
                    //   );
                    // },
                    controlLabelWrap: (Widget child, dynamic data) {
                      return Container(
                        margin: const EdgeInsets.only(bottom: 5),
                        child: child,
                      );
                    },
                    controlWrap: (Widget child, dynamic data) {
                      return Container(
                        margin: const EdgeInsets.only(bottom: 10),
                        child: child,
                      );
                    },
                  ),
                ),
                ElevatedButton(
                  onPressed: () async {
                    final formState = _key.currentState as JsonGenFormState;
                    try {
                      final data = await formState.validate();
                      debugPrint('提交成功 $data');
                    } catch (e) {
                      debugPrint('Validation error: $e');
                    }
                  },
                  child: const Text('提交'),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

通用参数

除了group, row, 和 col,所有类型都有以下通用参数。所有类型都有extra

字段 描述 类型 默认值 必填
type 类型 String ‘’
field 字段名称 String ‘’
label 标签 String - -
hiddenLabel 隐藏标签 bool false -
value 默认值 dynamic - -
disabled 禁用 bool false -
readonly 只读 bool false -
rules 验证规则 List [] -
extra 额外参数 dynamic - -

表单类型

分组 (group)

字段 描述 类型 默认值 必填
type 类型 String ‘group’
field 字段名称 String ‘’ -
label 标签 String ‘’ -
hiddenLabel 隐藏标签 bool ‘’ -
children 子表单 List [] -

文本框 (text)

字段 描述 类型 默认值 必填
type 类型 String ‘text’
placeholder 占位符 String - -
通用参数 - - - -

密码框 (password)

字段 描述 类型 默认值 必填
type 类型 String ‘password’
placeholder 占位符 String - -
通用参数 - - - -

多行文本框 (textarea)

字段 描述 类型 默认值 必填
type 类型 String ‘textarea’
placeholder 占位符 String - -
通用参数 - - - -

数字输入框 (number)

字段 描述 类型 默认值 必填
type 类型 String ‘number’
placeholder 占位符 String - -
通用参数 - - - -

单选按钮 (radio)

字段 描述 类型 默认值 必填
type 类型 String ‘radio’
options 选项 List [] -
direction 选项方向 String ‘horizontal’ -
itemHorizontalSpace 项目水平间距 double 16 -
itemVerticalSpace 项目垂直间距 double 8 -
通用参数 - - - -

复选框 (checkbox)

字段 描述 类型 默认值 必填
type 类型 String ‘checkbox’
options 选项 List [] -
direction 选项方向 String ‘horizontal’ -
itemHorizontalSpace 项目水平间距 double 16 -
itemVerticalSpace 项目垂直间距 double 8 -
通用参数 - - - -

下拉选择框 (select)

字段 描述 类型 默认值 必填
type 类型 String ‘select’
options 选项 List [] -
multiple 多选 bool false -
通用参数 - - - -

开关 (switch)

字段 描述 类型 默认值 必填
type 类型 String ‘switch’
通用参数 - - - -

多媒体上传 (media)

字段 描述 类型 默认值 必填
type 类型 String ‘media’
mediaType 媒体类型 (media, image, video) String ‘media’ -
multiple 多次上传 bool false -
通用参数 - - - -

iOS配置 (info.plist)

<key>NSCameraUsageDescription</key>
<string>需要相机拍照或扫描二维码</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>需要访问相册选择照片或视频</string>
<key>NSMicrophoneUsageDescription</key>
<string>需要麦克风录制视频</string>

Android配置 (AndroidManifest.xml)

<uses-permission android:name="android.permission.CAMERA" />

更多关于Flutter自动生成表单插件json_gen_form的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自动生成表单插件json_gen_form的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用json_gen_form插件自动生成表单的示例代码。这个插件允许你通过JSON配置来生成表单,非常适合需要动态生成表单的场景。

首先,确保你已经在pubspec.yaml文件中添加了json_gen_form依赖:

dependencies:
  flutter:
    sdk: flutter
  json_gen_form: ^最新版本号  # 请替换为实际的最新版本号

然后,运行flutter pub get来安装依赖。

接下来,创建一个JSON文件(例如form_config.json),用于定义表单的结构:

[
  {
    "type": "TextFormField",
    "key": "name",
    "label": "Name",
    "hintText": "Enter your name",
    "validator": {"required": true, "errorMessage": "Name is required"}
  },
  {
    "type": "DropdownButtonFormField",
    "key": "gender",
    "label": "Gender",
    "hintText": "Select your gender",
    "validator": {"required": true, "errorMessage": "Gender is required"},
    "options": [
      {"value": "male", "label": "Male"},
      {"value": "female", "label": "Female"}
    ]
  },
  {
    "type": "CheckboxListTile",
    "key": "interests",
    "label": "Interests",
    "title": "Select your interests",
    "options": [
      {"value": "sports", "label": "Sports"},
      {"value": "music", "label": "Music"},
      {"value": "reading", "label": "Reading"}
    ]
  },
  {
    "type": "ElevatedButton",
    "key": "submit",
    "label": "Submit",
    "onPressed": "submitForm"
  }
]

注意:json_gen_form插件的具体用法可能依赖于其内部实现和版本,上面的JSON配置是一个假设性的示例,实际使用时需要根据插件的文档进行调整。

接下来,在你的Flutter项目中编写代码来加载这个JSON配置并生成表单:

import 'package:flutter/material.dart';
import 'package:json_gen_form/json_gen_form.dart'; // 假设这是插件的导入路径
import 'dart:convert';
import 'package:flutter/services.dart' show rootBundle;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('JSON Generated Form'),
        ),
        body: FutureBuilder<String>(
          future: loadAsset(),
          builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
            if (snapshot.hasError) {
              return Center(child: Text('Failed to load asset: ${snapshot.error}'));
            } else if (snapshot.connectionState == ConnectionState.done) {
              final List formConfig = jsonDecode(snapshot.data!);
              return JsonGenForm(
                formConfig: formConfig,
                onFormSubmit: (Map<String, dynamic> formData) {
                  // 处理表单提交
                  print('Form Data: $formData');
                },
              );
            } else {
              return Center(child: CircularProgressIndicator());
            }
          },
        ),
      ),
    );
  }

  Future<String> loadAsset() async {
    return await rootBundle.loadString('assets/form_config.json');
  }
}

在这个示例中,FutureBuilder用于异步加载JSON配置文件。一旦文件加载完成,JsonGenForm组件将使用加载的配置来生成表单。onFormSubmit回调用于处理表单提交事件。

请注意,由于json_gen_form插件的具体实现可能有所不同,上面的代码可能需要根据插件的实际API进行调整。务必参考插件的官方文档和示例代码来获取最准确的信息。

此外,确保在pubspec.yaml文件的flutter部分下添加对form_config.json文件的引用:

flutter:
  assets:
    - assets/form_config.json

这样,你就可以在Flutter项目中通过JSON配置动态生成表单了。

回到顶部