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

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

Flutter Auto Form

pub package

Introduction

Are you tired of writing endless lines of code to create forms in your Flutter apps? Look no further! Our Flutter Auto Form package is here to revolutionize your form-building experience.

Our primary goal is to significantly reduce the amount of code required to create forms in Flutter. We achieve this by embracing a clear separation of concerns between form logic and form display.

With Flutter Auto Form, you write the form logic in pure Dart, without any direct mention of widgets. Instead, we introduce the AFWidget, which dynamically renders all the necessary widgets based on a straightforward form declaration—a simple Dart class that extends the TemplateForm class.

But that’s not all! Our package empowers you to design your custom fields and linked widgets, making nearly any form conceivable. Whether you’re working on basic forms or tackling complex ones, Flutter Auto Form has got you covered.

The true magic of Flutter Auto Form shines when you’re dealing with multiple forms, especially complex ones. All your validators are automatically called when you submit a form, and you can even create sub-forms that cascade into one another.

Dynamic form generation is also feasible but still in experimental mode. It is accessible through the JsonSchemaForm class.

Installation

To use this plugin, add flutter_auto_form as a dependency in your pubspec.yaml file.

dependencies:
  flutter:
    sdk: flutter

  # Your other packages ...

  flutter_auto_form: ^1.0.6

Support

  • Platforms: All platforms currently supported
  • Autofill hints: Automatic support through AFTextFieldType
  • Validators: Email, Url, Hex colour, Not null, Minimum string length, Same as another field, Alphanumeric
  • Fields: Password (auto obscure toggle), Text, Number, Model (built-in support for search through an API), Boolean, Sub-form (cascading forms), Select (dropdown field allowing only predefined values)
  • Custom code: You can customize and create new fields, validators, widgets as you please without even touching the source code of this package!

Usage

Step 1: Create a Form Class

The first step in creating a form with Flutter Auto Form is to create a class inheriting from the TemplateForm class.

import 'package:flutter_auto_form/flutter_auto_form.dart';

class LoginForm extends TemplateForm {
  @override
  final List<Field> fields = [
    AFTextField(
      id: 'identifier',
      name: 'Identifier',
      validators: [
        MinimumStringLengthValidator(
          5,
              (e) => 'Min 5 characters, currently ${e?.length ?? 0} ',
        )
      ],
      type: AFTextFieldType.USERNAME,
    ),
    AFTextField(
      id: 'password',
      name: 'Password',
      validators: [
        MinimumStringLengthValidator(
          6,
              (e) => 'Min 6 characters, currently ${e?.length ?? 0} ',
        )
      ],
      type: AFTextFieldType.PASSWORD,
    ),
    AFBooleanField(
      id: 'accept-condition',
      name: 'Accept terms',
      validators: [ShouldBeTrueValidator('Please accept terms to continue?')],
      value: false,
    )
  ];
}

Step 2: Add the AFWidget

The second and (already) last step is to add the AFWidget wherever you would like to display a form.

AFWidget<LoginForm>(
  formBuilder: () => LoginForm(),
  submitButton: (Function({bool showLoadingDialog}) submit) => Padding(
    padding: const EdgeInsets.only(top: 32),
    child: MaterialButton(
      child: Text('Submit'),
      onPressed: () => submit(showLoadingDialog: true),
    ),
  ),
  onSubmitted: (LoginForm form) {
    // Do whatever you want when the form is submitted
    print(form.toMap());
  },
);

Example

A demo video can be found here. The four forms displayed in the video are all created with Flutter Auto Form, even the model search field.

The source code is located in the example folder.

Full Example Code

Here is a complete example demonstrating how to use Flutter Auto Form in a Flutter application.

import 'package:auto_form_example/forms/order_form.dart';
import 'package:flutter/material.dart';
import 'package:flutter_auto_form/flutter_auto_form.dart';

import 'entities/json_schema.dart';
import 'forms/login_form.dart';
import 'forms/registration_form.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AFTheme(
      data: const AFThemeData(),
      child: MaterialApp(
        title: 'Auto Form Demo',
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          primarySwatch: Colors.blue,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        home: const MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: DefaultTabController(
        length: 4,
        child: Scaffold(
          body: SingleChildScrollView(
            child: SizedBox(
              height: MediaQuery.of(context).size.height - 50,
              child: Column(
                children: [
                  Expanded(
                    child: TabBarView(
                      children: [
                        FormShowcaseTile(
                          title: 'Json Schema Form',
                          child: AFWidget<JsonSchemaForm>(
                            formBuilder: () => JsonSchemaForm.fromJson(jsonSchema),
                            submitButton: (Function() submit) {
                              return Padding(
                                padding: const EdgeInsets.only(top: 32),
                                child: ElevatedButton(
                                  child: const Text('Submit'),
                                  onPressed: () => submit(),
                                ),
                              );
                            },
                            onSubmitted: (JsonSchemaForm form) {
                              print(form.toMap());
                            },
                          ),
                        ),
                        SingleChildScrollView(
                          child: FormShowcaseTile(
                            title: 'Login form',
                            child: AFWidget<LoginForm>(
                              handleErrorOnSubmit: print,
                              formBuilder: () => LoginForm(),
                              submitButton: (Function() submit) {
                                return Padding(
                                  padding: const EdgeInsets.only(top: 32),
                                  child: ElevatedButton(
                                    child: const Text('Submit'),
                                    onPressed: () => submit(),
                                  ),
                                );
                              },
                              onSubmitted: (LoginForm form) async {
                                await Future.delayed(const Duration(seconds: 2));
                                print(form.toMap());
                              },
                            ),
                          ),
                        ),
                        FormShowcaseTile(
                          title: 'Registration form',
                          child: AFWidget<RegistrationForm>(
                            formBuilder: () => RegistrationForm(),
                            submitButton: (Function() submit) {
                              return Padding(
                                padding: const EdgeInsets.only(top: 32),
                                child: ElevatedButton(
                                  child: const Text('Submit'),
                                  onPressed: () {
                                    submit();
                                  },
                                ),
                              );
                            },
                            onSubmitted: (RegistrationForm form) {
                              print(form.toMap());
                            },
                          ),
                        ),
                        SingleChildScrollView(
                          child: FormShowcaseTile(
                            title: 'Order form',
                            child: AFWidget<OrderForm>(
                              formBuilder: () => OrderForm(),
                              submitButton: (Function() submit) {
                                return Padding(
                                  padding: const EdgeInsets.only(top: 32),
                                  child: ElevatedButton(
                                    child: const Text('Submit'),
                                    onPressed: () => submit(),
                                  ),
                                );
                              },
                              onSubmitted: (OrderForm form) {
                                print(form.toMap());
                              },
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  const Padding(
                    padding: EdgeInsets.all(16),
                    child: TabPageSelector(),
                  )
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class FormShowcaseTile extends StatelessWidget {
  const FormShowcaseTile({Key? key, required this.child, required this.title})
      : super(key: key);

  final String title;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Center(
        child: Container(
          margin: const EdgeInsets.symmetric(vertical: 64, horizontal: 24),
          padding: const EdgeInsets.all(24),
          decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(16),
              boxShadow: const [
                BoxShadow(
                  blurRadius: 16,
                  color: Colors.black12,
                  offset: Offset(0, 10),
                ),
              ],
              color: Colors.white),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Padding(
                padding: const EdgeInsets.only(bottom: 16),
                child: Text(
                  title,
                  textAlign: TextAlign.center,
                  style: const TextStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                    color: Colors.blueAccent,
                  ),
                ),
              ),
              child,
            ],
          ),
        ),
      ),
    );
  }
}

Advanced Usage

If you need to create your own field (color field, image field, …), you can always create it by overriding the Field class. Then to display a custom widget, create a stateful widget that extends the FieldStatefulWidget, and of which the state extends the FieldState class.

Feedback and Contributions

This package is still under construction! Do not hesitate to create an issue on the GitHub page if you find any bugs or if you would like to see a new type of validator, field!


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

1 回复

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


当然,以下是一个关于如何使用 flutter_auto_form 插件的示例代码,它展示了如何自动生成表单。请注意,这个示例假设你已经安装了 flutter_auto_form 插件并正确配置了你的 Flutter 项目。

首先,确保你的 pubspec.yaml 文件中包含了 flutter_auto_form 依赖:

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

然后,运行 flutter pub get 来获取依赖。

接下来,在你的 Dart 文件中使用 flutter_auto_form 来自动生成表单。以下是一个简单的示例:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Auto Form Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: AutoFormScreen(),
    );
  }
}

class AutoFormScreen extends StatefulWidget {
  @override
  _AutoFormScreenState createState() => _AutoFormScreenState();
}

class _AutoFormScreenState extends State<AutoFormScreen> {
  // 定义一个表单模型
  final formModel = [
    AutoFormFieldModel(
      type: FieldType.text,
      label: 'Name',
      name: 'name',
      validators: [RequiredValidator()],
    ),
    AutoFormFieldModel(
      type: FieldType.email,
      label: 'Email',
      name: 'email',
      validators: [RequiredValidator(), EmailValidator()],
    ),
    AutoFormFieldModel(
      type: FieldType.password,
      label: 'Password',
      name: 'password',
      validators: [RequiredValidator()],
      obscureText: true,
    ),
  ];

  // 提交表单的回调
  void onFormSubmit(Map<String, dynamic> formData) {
    print('Form Data: $formData');
    // 在这里处理表单数据,比如发送到服务器
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Auto Form Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: AutoForm(
          formModel: formModel,
          onFormSubmit: onFormSubmit,
        ),
      ),
    );
  }
}

在这个示例中:

  1. AutoFormFieldModel 用于定义表单字段的模型,包括字段类型、标签、名称和验证器。
  2. AutoForm 组件用于生成表单,它接收 formModelonFormSubmit 回调作为参数。
  3. onFormSubmit 回调在表单提交时被调用,你可以在这里处理表单数据,比如发送到服务器。

请确保你根据 flutter_auto_form 插件的实际文档和 API 适配这个示例,因为插件的 API 可能会随着版本更新而变化。

回到顶部