Flutter表单构建插件formify的使用

Flutter表单构建插件formify的使用

Formify 是一个功能丰富且可定制的 Flutter 表单处理库,旨在简化在 Flutter 应用程序中创建和管理表单的过程。通过 Formify,您可以轻松地构建动态表单、验证用户输入并处理表单提交。

特性

Formify 提供了多种功能来帮助您创建和管理表单,包括:

  • 动态表单生成:Formify 提供了一种清晰直观的方式来基于您的数据模型动态生成表单。
  • 可定制字段:自定义表单字段、标签、图标、验证规则等以匹配应用程序的设计和需求。
  • 验证规则:轻松应用内置或自定义验证规则来验证用户输入并提供有意义的错误消息。
  • 实时验证:Formify 在用户与表单交互时执行实时验证,立即反馈输入的有效性。
  • 错误处理:轻松管理和显示验证错误,使用户清楚地知道需要进行哪些更正。
  • 高效的表单状态管理:Formify 高效地管理表单字段的状态,减少 Flutter 应用程序中的状态管理复杂性。
  • 富文本编辑:支持各种输入类型,包括文本、数字、电子邮件、多行等。
  • 密码切换:为用户方便创建具有可切换可见性的密码字段。

使用方法

首先,创建一个继承自 FormifyForms 的类,并准备将要使用的属性。您可以使用以下代码:

class FormDemo extends FormifyForms {
  [@override](/user/override)
  List<Attribute> get attributes => [
    FormifyAttribute('username'),
    FormifyAttribute('password', FormifyType.password),
  ];
}

getWidgets() 方法返回表示表单字段的 Widget 列表。您可以使用此方法将表单字段添加到您的应用程序中。

例如,以下代码将表单字段添加到 Column 小部件中:

Column(
  children: formDemo.getWidgets(),
)

您还可以使用展开操作符(...)将表单字段添加到其他小部件中。例如,以下代码将表单字段添加到 Column 小部件中:

Column(
  children: [
    ...formDemo.getWidgets(),
    FilledButton(
      onPressed: () {},
      child: const Text('Login'),
    ),
  ],
)

表单布局

您还可以通过使用 FormifyRowAttributeFormifyAttribute 结合来创建水平表单布局。以下是一个示例代码片段,演示如何实现这一点:

class FormDemo extends FormifyForms {
  [@override](/user/override)
  List<Attribute> get attributes => [
    FormifyAttribute('username'),
    FormifyAttribute('password', FormifyType.password),
    FormifyRowAttribute([
      FormifyAttribute('phone_number', FormifyType.phone),
      FormifyAttribute('email_address', FormifyType.email),
    ]),
  ];
}

水平表单布局

文档

属性类型

class FormDemo extends FormifyForms {
  [@override](/user/override)
  List<Attribute> get attributes => [
    FormifyAttribute('username'),
    FormifyAttribute('password', FormifyType.password),
  ];
}

这段代码定义了一个名为 FormDemo 的类,该类扩展了 FormifyForms 类。FormifyForms 类是一个基类,提供了所有表单字段的通用功能。attributes 属性是一个映射,将属性名称映射到属性值。在这个例子中,username 属性被设置为默认值 FormifyType.text(如果没有定义),而 password 属性被设置为 FormifyType.password

类型 描述
FormifyType.text 默认类型。它返回一个通用的 TextFormField
FormifyType.numeric 显示的是数字键盘。
FormifyType.password obscureText 属性设置为 true
FormifyType.email 显示的是电子邮件键盘。
FormifyType.multiline 显示的是多行键盘。
FormifyType.phone 显示的是电话键盘。
FormifyType.name TextCapitalization 属性设置为 TextCapitalization.words

自定义标签

默认情况下,文本表单字段上显示的标签将采用先前创建的属性键,下划线替换为空格并将首字母大写。例如,如果属性是 fist_name,标签将是 First Name

您可以通过添加 labels 属性来自定义标签,如以下示例所示:

class FormDemo extends FormifyForms {
  [@override](/user/override)
  List<Attribute> get attributes => [
    FormifyAttribute('username'),
    FormifyAttribute('password', FormifyType.password),
  ];

  [@override](/user/override)
  Map<String, String> get labels => {
    'username': 'Username or Email Address',
  };
}

您不需要定义所有属性,只需定义您想要更改的那些即可。

自定义标签

验证

您可以通过添加 rules 属性来自定义验证规则,如以下示例所示:

[@override](/user/override)
Map<String, List<FormifyRule>> get rules => {
  'username': [FormifyRule.required],
  'password': [FormifyRule.required, FormifyRule.min(5)],
};

rules 属性是一个映射,将属性名称映射到一个验证规则列表。在此示例中,username 属性是必填项,而 password 属性也是必填项,并且必须至少包含 5 个字符。

如果用户为某个属性输入无效值,则会显示错误消息。错误消息将根据验证规则进行自定义。例如,如果用户为 username 属性输入空值,则错误消息将是 "Username is required."

以下是可用的验证规则列表:

规则 示例 描述
required FormifyRule.required 字段是必填项。如果字段为空,则表单不会提交。
numeric FormifyRule.numeric 字段必须是数字。
integer FormifyRule.integer 字段必须是整数。
double FormifyRule.double 字段必须是双精度值。
between FormifyRule.between(1, 2) 字段必须是一个介于 1 和 2 之间的数字。
min FormifyRule.min(10) 字段必须包含至少 10 个字符。
max FormifyRule.max(10) 字段最多只能包含 10 个字符。
gt FormifyRule.gt(10) 字段必须是一个大于 10 的数字。
gte FormifyRule.gte(10) 字段必须是一个大于或等于 10 的数字。
lt FormifyRule.lt(10) 字段必须是一个小于 10 的数字。
lte FormifyRule.lte(10) 字段必须是一个小于或等于 10 的数字。
starts_with FormifyRule.starts_with('mr') 字段必须以 ‘mr’ 开头。
ends_with FormifyRule.ends_with('S.Kom') 字段必须以 ‘S.Kom’ 结尾。
same FormifyRule.same('good') 字段必须与 ‘good’ 相同。
lowercase FormifyRule.lowercase 字段必须是小写字母。
uppercase FormifyRule.uppercase 字段必须是大写字母。
alpha_num FormifyRule.alphaNumeric 字段必须是字符串或数字。
email FormifyRule.email 字段必须是有效的电子邮件地址。
ip FormifyRule.ip 字段必须是有效的 IP 地址。
url FormifyRule.url 字段必须是有效的 URL。
in FormifyRule.inItems(['you','me','they']) 字段必须在列表中。
not_in FormifyRule.notInItems(['you','me','they']) 字段不能在列表中。
regex FormifyRule.regex(r"^dog") 字段必须匹配正则表达式。

您还可以通过定义一个扩展 FormifyRule 的类并将其添加到 rules 属性中来创建自定义验证规则。例如:

class MyPhoneValidation extends FormifyRule {
  [@override](/user/override)
  String? call(String attribute, String value) {
    RegExp phoneNumberRegex = RegExp(r'^\+26\d{10,}$');
    if (!phoneNumberRegex.hasMatch(value)) {
      return '$attribute should start with +26 and minimum 12 digit';
    }
    return null;
  }
}
[@override](/user/override)
Map<String, List<FormifyRule>> get rules => {
  'phone_number': [FormifyRule.required, MyPhoneValidation()],
};

您还可以通过利用 validationMessage 属性进一步自定义验证消息。此属性允许您为特定验证规则定义自定义消息。只需包含验证规则及其所需的消息即可。系统会自动替换诸如 :attribute:input 等占位符为相应的属性名称和用户输入。此外,您还可以使用特定类型的占位符如 :number:min:max:pattern:items 来表示实际值。

[@override](/user/override)
Map<String, String> get validationMessage => {
  'min': 'The :attribute must contain at least :number characters.',
  'between': 'The :attribute value :input is not between :min and :max.',
  'in': 'The :attribute is not between :min and :max.',
  'starts_with': 'The :attribute must start with :pattern',
};

默认情况下,Formify 会自动验证您的输入。但是,您可以通过添加 isAutoValidation 属性并将其设置为 false 来更改此行为。

[@override](/user/override)
bool get isAutoValidation => false;

然后,您可以通过调用 isFormValid() 函数来验证您的表单。此函数返回一个 bool,您可以根据其结果决定下一步的操作。

FilledButton(
  onPressed: () {
    if (formDemo.isFormValid()) {
      //DO SOMETHING
    }
  },
  child: const Text('Login'),
),

手动错误消息

您可以通过调用 addErrorMessagesetErrorMessagesetErrorMessages 函数手动设置错误消息。例如:

addErrorMessage 将错误消息追加到现有的错误消息列表中。

FilledButton(
  onPressed: () {
    formDemo.addErrorMessage('username', 'manual error message');
  },
  child: const Text('Login'),
),

setErrorMessage 将错误消息替换为现有的错误消息。

FilledButton(
  onPressed: () {
    formDemo.setErrorMessage('username', 'manual error message');
  },
  child: const Text('Login'),
),

setErrorMessages 将错误消息替换为现有的错误消息列表。

FilledButton(
  onPressed: () {
    formDemo.setErrorMessages('username', ['manual error message', 'manual error message too']);
  },
  child: const Text('Login'),
),

自定义表单小部件(InputDecoration)

您可以通过添加 inputDecoration 属性并将其设置为您所需的值来自定义文本表单字段。

[@override](/user/override)
InputDecoration? get inputDecoration => 
    const InputDecoration(
      border: OutlineInputBorder(),
      focusedBorder: OutlineInputBorder(
        borderSide: BorderSide(color: Colors.purple),
      ),
    );

自定义装饰

自定义表单小部件(formBuilder)

如果您想更深入地自定义,可以添加 formBuilder 属性。表单生成器是一个返回 Widget 的函数,接受三个参数:BuildContextFormify 对象和 FormifyTextField 小部件。

Formify 对象允许您获取以下值:

  • attribute:字段的属性键。
  • type:字段的 FormifyType
  • label:表单的标签。
  • value:已输入的值。
  • errors:错误值的字符串列表(如果有)。
  • error:错误值的字符串。
  • isLoading:一个布尔值,指示表单是否处于加载状态。通常用于在加载时使表单只读。
  • isRequired:一个布尔值,指示表单是否必填,当其规则包含 FormifyRule.required 时。
  • formKey:表单的 GlobalKey<FormFieldState>
  • controller:表单的 TextEditingController
  • keyboardType:表单的 TextInputType
  • textCapitalization:表单的 TextCapitalization
  • obscureText:表单的 obscureText
  • onChanged:可以更新表单值的函数。
  • clearErrorMessages:可以清除表单错误消息的函数。
  • toggleObscureText:可以切换表单 obscureText 的函数。

FormifyTextField 小部件是一个包含 TextFormField 小部件的自定义小部件。因此,您可以使用 copyWith() 更改其属性。这些属性几乎与 TextFormField 相同。

例如,如果您想为用户名和密码字段设置不同的前缀图标,您可以使用 copyWith() 方法修改 FormifyTextField 并返回它。

[@override](/user/override)
FormifyFormBuilder? get formBuilder => (
    BuildContext context, 
    Formify formify, 
    FormifyTextField child,
) {
  if (formify.attribute == 'username') {
    return child.copyWith(prefixIcon: const Icon(Icons.person));
  }
  if (formify.attribute == 'password') {
    return child.copyWith(prefixIcon: const Icon(Icons.lock));
  }
  return child;
};

自定义表单字段

formBuilder 允许您创建一个完全新的小部件。每当表单的任何属性的值、加载状态或错误状态发生变化时,formBuilder 函数都会被调用。

自定义表单分隔符小部件

Formify 使用高度为 16 的 SizedBox 分隔表单。如果您认为这不合适,可以通过添加 separatorBuilder 属性来自定义它,如以下示例所示:

[@override](/user/override)
FormifySeparatorBuilder? get separatorBuilder => (
  BuildContext context,
  Formify formify,
  Widget child,
) {
  return const SizedBox(height: 20);
};

初始值

假设在编辑表单的情况下,您需要一个初始值来填充表单的初始值。您可以以两种方式实现这一点。

一次设置一个初始值。

[@override](/user/override)
void initState() {
  super.initState();
  formDemo.setInitialValue('username', 'thisismyusername');
}

一次性批量设置初始值。

[@override](/user/override)
void initState() {
  super.initState();
  formDemo.setInitialValues({
    'username': 'thisismyusername',
    'password': 'password',
  });
}

完整示例

以下是一个完整的示例,展示了如何使用 Formify 创建一个简单的登录表单:

import 'package:example/form_demo.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Formify Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

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

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final formDemo = FormDemo();

  [@override](/user/override)
  void initState() {
    super.initState();
    formDemo.setInitialValues({
      'first_name': 'Agung',
      'last_name': 'Budi',
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Formify Demo'),
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
        child: Column(
          children: [
            ...formDemo.getWidgets(),
            const SizedBox(height: 16),
            SizedBox(
              width: double.infinity,
              height: 50,
              child: FilledButton(
                onPressed: () {
                  if (formDemo.isFormValid()) {
                    //DO SOMETHING
                  }
                },
                child: const Text('Login'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

更多关于Flutter表单构建插件formify的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


当然,下面是一个关于如何使用Flutter的formify插件来构建表单的示例代码。formify是一个用于简化Flutter表单构建的插件,通过提供一套声明式的API来快速构建表单。

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

dependencies:
  flutter:
    sdk: flutter
  formify: ^x.y.z  # 请替换为最新版本号

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

接下来是一个完整的示例代码,展示了如何使用formify来构建一个简单的登录表单:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: LoginFormScreen(),
    );
  }
}

class LoginFormScreen extends StatefulWidget {
  @override
  _LoginFormScreenState createState() => _LoginFormScreenState();
}

class _LoginFormScreenState extends State<LoginFormScreen> {
  final formController = FormController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Login Form'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Formify(
          formController: formController,
          child: Column(
            children: [
              FormifyTextField(
                formController: formController,
                validators: [
                  RequiredValidator(errorText: 'Email is required'),
                  EmailValidator(errorText: 'Invalid email address'),
                ],
                decoration: InputDecoration(
                  labelText: 'Email',
                ),
              ),
              FormifyTextField(
                formController: formController,
                obscureText: true,  // Password field
                validators: [
                  RequiredValidator(errorText: 'Password is required'),
                  MinLengthValidator(minLength: 6, errorText: 'Password must be at least 6 characters long'),
                ],
                decoration: InputDecoration(
                  labelText: 'Password',
                ),
              ),
              SizedBox(height: 20),
              FormifyButton(
                formController: formController,
                onPressed: () async {
                  final isValid = await formController.validate();
                  if (isValid) {
                    // Handle form submission
                    print('Form is valid, submit it!');
                    // Example: Accessing form values
                    final email = formController.values['email'];
                    final password = formController.values['password'];
                    print('Email: $email, Password: $password');
                  }
                },
                child: Text('Login'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

在这个示例中:

  1. 我们创建了一个FormController实例来管理表单的状态和验证。
  2. 使用Formify小部件作为表单的容器,并将formController传递给它。
  3. 使用FormifyTextField来创建两个输入字段,一个用于电子邮件,另一个用于密码。我们为这些字段添加了验证器,如RequiredValidatorEmailValidator
  4. 使用FormifyButton来创建一个提交按钮,并在点击时触发验证。如果验证通过,我们可以访问表单的值并进行进一步处理。

这个示例展示了如何使用formify插件来简化Flutter表单的构建和验证过程。希望这对你有所帮助!

回到顶部