Flutter表单管理插件tf_form的使用

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

Flutter表单管理插件tf_form的使用

tf_form 是一个用于创建表单容器的 Flutter 包,可以将多个常见的表单组件组合在一起,并自动进行验证。

安装

在你的 Flutter 项目的 pubspec.yaml 文件中添加以下依赖:

dependencies:
  ...
  tf_form: ^0.0.6

然后在你的库中添加以下导入语句:

import 'package:tf_form/tf_form.dart';

组件

TFForm

TFForm 小部件作为表单容器,用于将多个表单组件组合在一起并自动验证。它需要一个 GlobalKey 来允许稍后验证表单。你还可以通过传递参数来自定义错误消息或样式。

final _formKey = GlobalKey<TFFormState>();

[@override](/user/override)
Widget build(BuildContext context) {
  // 使用上面创建的 _formKey 构建 TFForm 小部件。
  return TFForm(
    key: _formKey,
    child: Column(
      children: <Widget>[
        // 在这里添加表单小部件和 ElevatedButton。
      ],
    ),
  );
}

TFTextField

TFTextField 是最常用的表单组件之一,允许用户输入文本,可以通过硬件键盘或屏幕键盘输入。

TFTextField(
  title: "Nickname",
  hintText: "Enter a nickname",
  controller: nicknameController,
  validationTypes: const [
    TFValidationType.required,
  ],
),

该包支持 iOS 的数字输入,并带有默认的“完成”按钮。要启用此功能,只需指定以下键盘类型之一:

TextInputType.number,
TextInputType.phone,
TextInputType.numberWithOptions(decimal: true),

TFDropdownField

TFDropdownField 允许用户从下拉列表中选择一个值。

TFDropdownField(
  title: "Role",
  items: [
    TFOptionItem<String>(title: "Member", value: "member"),
    TFOptionItem<String>(title: "Administrator", value: "admin"),
    TFOptionItem<String>(title: "Manager", value: "manager")
  ],
  controller: roleController,
  initialValue: "member",
  validationTypes: const [
    TFValidationType.required,
  ],
),

TFDateField

TFDateField 允许用户选择日期。

TFDateField(
  title: "Birthday",
  initialDate: DateTime.now(),
  firstDate: DateTime.now().subtract(const Duration(days: 365)),
  lastDate: DateTime.now().add(const Duration(days: 365)),
  controller: birthdayController,
  validationTypes: const [
    TFValidationType.required,
  ],
),

TFRadioGroup

TFRadioGroup 允许用户从多个选项中选择一个。

TFRadioGroup<String>(
  title: "Gender",
  initialValue: "male",
  items: [
    TFOptionItem<String>(title: "Male", value: "male"),
    TFOptionItem<String>(title: "Female", value: "female"),
    TFOptionItem<String>(title: "Other", value: "other"),
  ],
  onChanged: (selectedItem) {
    print("$selectedItem");
  },
  validationTypes: const [
    TFValidationType.requiredIfHas,
  ],
  relatedController: nicknameController,
),

TFCheckboxGroup

TFCheckboxGroup 允许用户选择多个项目。

TFCheckboxGroup<String>(
  title: "Which social network do you usually use ?",
  initialValues: const ["fb", "telegram"],
  items: [
    TFOptionItem<String>(title: "Facebook", value: "fb"),
    TFOptionItem<String>(title: "Twitter", value: "twitter"),
    TFOptionItem<String>(title: "Linkedin", value: "linkedin"),
    TFOptionItem<String>(title: "Telegram", value: "telegram"),
  ],
  onChanged: (List<String> values) {
    print("$values");
  },
  validationTypes: const [
    TFValidationType.required,
  ],
),

TFRecaptchaField

TFRecaptchaField 用于加载 Google 的 reCAPTCHA v3 令牌,并将其设置到一个 TextEditingController 实例中,以便与其他表单字段一起提交。

TFRecaptchaField(controller: recaptchaController, uri: Uri.parse("https://www.anhcode.com/recaptcha.html")),

基本用法

  1. 首先,创建一个 TFForm
  2. 将上述表单组件之一作为 TFForm 的子组件添加。TFForm 可以使所有组件一次性验证变得更加容易。
  3. 最后,创建一个按钮来验证表单。
ElevatedButton(
  onPressed: () {
    _formKey.currentState!.validate();
  },
  child: const Text('Submit'),
),

示例代码

以下是一个完整的示例代码,展示了如何使用 tf_form 包创建一个包含多个表单组件的表单。

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

void main() => runApp(const MyApp());
const appTitle = 'TechFusion\'s Form Validation';

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: appTitle,
      debugShowCheckedModeBanner: false,
      theme: ThemeData(),
      home: const DemoFormPage(),
    );
  }
}

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

  [@override](/user/override)
  DemoFormPageState createState() {
    return DemoFormPageState();
  }
}

class DemoFormPageState extends State<DemoFormPage> {
  final _personalFormKey = GlobalKey<TFFormState>();
  final nicknameController = TextEditingController();
  final emailController = TextEditingController();
  final birthdayController = TextEditingController();
  final phoneController = TextEditingController();
  final heightController = TextEditingController();
  final roleController = TextEditingController(text: "member");
  final recaptchaController = TextEditingController();

  final _addressesFormKey = GlobalKey<TFFormState>();
  final address1Controller = TextEditingController();
  final address2Controller = TextEditingController();
  final addressTypeController = TextEditingController();

  final _securityFormKey = GlobalKey<TFFormState>();
  final passwordController = TextEditingController();
  final confirmPasswordController = TextEditingController();

  [@override](/user/override)
  Widget build(BuildContext context) {
    // 使用 _formKey 创建一个 Form 小部件。
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: AppBar(
          bottom: const TabBar(
            tabs: [
              Tab(text: "Personal Info"),
              Tab(text: "Addresses"),
              Tab(text: "Security"),
            ],
          ),
          title: const Text(appTitle),
        ),
        body: TabBarView(
          children: [
            _buildPersonalInfoTab(),
            _buildAddressesTab(),
            _buildPSecurityTab(),
          ],
        ),
      ),
    );
  }

  Widget _buildPersonalInfoTab() {
    return SingleChildScrollView(
      child: TFForm(
        key: _personalFormKey,
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              TFTextField(
                title: "Nickname",
                hintText: "Enter a nickname",
                controller: nicknameController,
                validationTypes: const [
                  TFValidationType.required,
                ],
              ),
              const SizedBox(height: 15),
              TFTextField(
                title: "Email",
                hintText: "ben@somewhere.com",
                controller: emailController,
                validationTypes: const [
                  TFValidationType.required,
                  TFValidationType.emailAddress,
                ],
              ),
              const SizedBox(height: 15),
              const SizedBox(height: 15),
              TFDropdownField(
                title: "Role",
                items: [
                  TFOptionItem<String>(title: "Member", value: "member"),
                  TFOptionItem<String>(title: "Administrator", value: "admin"),
                  TFOptionItem<String>(title: "Manager", value: "manager")
                ],
                valueController: roleController,
                validationTypes: const [
                  TFValidationType.required,
                ],
              ),
              const SizedBox(height: 15),
              TFTextField(
                title: "Phone",
                hintText: "Enter a phone",
                controller: phoneController,
                keyboardType: TextInputType.number,
                validationTypes: const [
                  TFValidationType.required,
                  TFValidationType.phone,
                ],
              ),
              const SizedBox(height: 15),
              TFTextField(
                title: "Height (cm)",
                hintText: "Enter height",
                controller: heightController,
                keyboardType: const TextInputType.numberWithOptions(decimal: true),
                validationTypes: const [
                  TFValidationType.required,
                ],
              ),
              const SizedBox(height: 20),
              TFCheckboxGroup<String>(
                title: "Which social network do you usually use ?",
                initialValues: const ["fb", "telegram"],
                items: [
                  TFOptionItem<String>(title: "Facebook", value: "fb"),
                  TFOptionItem<String>(title: "Twitter", value: "twitter"),
                  TFOptionItem<String>(title: "Linkedin", value: "linkedin"),
                  TFOptionItem<String>(title: "Telegram", value: "telegram"),
                ],
                onChanged: (List<String> values) {
                  print("$values");
                },
                validationTypes: const [
                  TFValidationType.required,
                ],
              ),
              const SizedBox(height: 20),
              TFRadioGroup<String>(
                title: "Gender",
                initialValue: "male",
                items: [
                  TFOptionItem<String>(title: "Male", value: "male"),
                  TFOptionItem<String>(title: "Female", value: "female"),
                  TFOptionItem<String>(title: "Other", value: "other"),
                ],
                onChanged: (selectedItem) {
                  print("$selectedItem");
                },
                validationTypes: const [
                  TFValidationType.requiredIfHas,
                ],
                relatedController: nicknameController,
              ),
              TFRecaptchaField(controller: recaptchaController, uri: Uri.parse("https://www.anhcode.com/recaptcha.html")),
              const SizedBox(height: 40),
              ElevatedButton(
                onPressed: () {
                  _personalFormKey.currentState!.validate();
                },
                child: const Text('Submit'),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildAddressesTab() {
    return TFForm(
      key: _addressesFormKey,
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            TFTextField(
              title: "Type",
              controller: addressTypeController,
              validationTypes: const [],
            ),
            const SizedBox(height: 10),
            TFTextField(
              title: "Address 1",
              controller: address1Controller,
              validationTypes: const [
                TFValidationType.required,
              ],
            ),
            const SizedBox(height: 10),
            TFTextField(
              title: "Address 2",
              controller: address2Controller,
              validationTypes: const [],
            ),
            const SizedBox(height: 10),
            ElevatedButton(
              onPressed: () {
                _addressesFormKey.currentState!.validate();
              },
              child: const Text('Submit'),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildPSecurityTab() {
    return TFForm(
      key: _securityFormKey,
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            TFTextField(
              title: "New password",
              controller: passwordController,
              validationTypes: const [
                TFValidationType.required,
                TFValidationType.password,
              ],
            ),
            const SizedBox(height: 10),
            TFTextField(
              title: "Confirm",
              controller: confirmPasswordController,
              relatedController: passwordController,
              retypeInvalidMessage: "",
              validationTypes: const [
                TFValidationType.required,
                TFValidationType.retype,
              ],
            ),
            const SizedBox(height: 10),
            ElevatedButton(
              onPressed: () {
                _securityFormKey.currentState!.validate();
              },
              child: const Text('Submit'),
            ),
          ],
        ),
      ),
    );
  }
}

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

1 回复

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


在Flutter中,tf_form 是一个用于表单管理的强大插件,它简化了表单字段的创建、验证和管理过程。以下是一个使用 tf_form 插件的示例代码案例,展示了如何创建一个简单的表单并进行验证。

首先,确保在你的 pubspec.yaml 文件中添加 tf_form 依赖:

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

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

接下来,创建一个简单的 Flutter 应用,展示如何使用 tf_form 插件:

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

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

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

class MyFormPage extends StatefulWidget {
  @override
  _MyFormPageState createState() => _MyFormPageState();
}

class _MyFormPageState extends State<MyFormPage> {
  final formKey = GlobalKey<FormState>();
  late TFFormController formController;

  @override
  void initState() {
    super.initState();

    // 定义表单字段和验证规则
    formController = TFFormController([
      TFFormField(
        name: 'name',
        validators: [
          TFRequiredValidator(errorText: 'Name is required'),
          TFLengthValidator(minLength: 3, maxLength: 20, errorText: 'Name must be between 3 and 20 characters'),
        ],
      ),
      TFFormField(
        name: 'email',
        validators: [
          TFRequiredValidator(errorText: 'Email is required'),
          TFEmailValidator(errorText: 'Email is not valid'),
        ],
      ),
    ]);
  }

  @override
  void dispose() {
    formController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Form Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: formKey,
          child: Column(
            children: [
              TextFormField(
                decoration: InputDecoration(labelText: 'Name'),
                controller: formController.textEditingControllers['name']!,
                validator: (value) {
                  // 使用TFFormController进行验证时,这里不需要手动调用验证器
                  return null;
                },
              ),
              TextFormField(
                decoration: InputDecoration(labelText: 'Email'),
                controller: formController.textEditingControllers['email']!,
                validator: (value) {
                  // 使用TFFormController进行验证时,这里不需要手动调用验证器
                  return null;
                },
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () async {
                  // 触发验证
                  if (await formController.validate()) {
                    // 获取表单数据
                    final formData = await formController.toMap();
                    print('Form Data: $formData');
                    // 可以在这里处理表单提交,比如发送到服务器
                  }
                },
                child: Text('Submit'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

代码解释:

  1. 依赖导入:在 pubspec.yaml 中添加 tf_form 依赖。
  2. 表单控制器初始化:在 initState 方法中初始化 TFFormController,并定义表单字段和验证规则。
  3. 表单字段:使用 TextFormField 并将其 controller 属性设置为 TFFormController 中相应的 TextEditingController
  4. 表单验证:在按钮点击事件中,使用 formController.validate() 方法触发验证。如果验证通过,可以使用 formController.toMap() 方法获取表单数据。

这个示例展示了如何使用 tf_form 插件来管理表单字段和验证规则,从而简化了表单处理逻辑。根据实际需求,你可以进一步扩展和自定义表单字段和验证规则。

回到顶部