Flutter表单管理与状态管理插件bond_form_riverpod的使用

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

Flutter表单管理与状态管理插件bond_form_riverpod的使用

简介

Bond Form Riverpod 提供了与 Riverpod 的无缝集成,Riverpod 是一个流行的 Flutter 状态管理解决方案。通过这种集成,Bond Form Riverpod 使得在 Flutter 应用中创建复杂的表单变得简单,并且能够有效地管理状态。

Pub Version License: MIT

目录

特性

  1. 无缝集成: River Form Bond 提供了与 Riverpod 的平滑集成,使你能够专注于构建应用,而不是繁琐的样板代码。
  2. 强大的表单处理: 利用 Bond Form 的强大表单验证和管理功能,为基于表单的 Flutter 应用提供完整的解决方案。
  3. 自动资源清理: 使用 <AutoDisposeFormStateNotifier>,表单状态相关的资源将被自动清理,使得应用更节省内存。
  4. 灵活性: 你可以自定义表单行为和验证规则,使用 <FormStateNotifier><AutoDisposeFormStateNotifier>
  5. 类型安全: 强类型的特性帮助在编译时捕捉问题,而不是运行时。

安装

要使用 bond_form_riverpod,只需将其作为依赖项添加到你的 pubspec.yaml 文件中:

dependencies:
  bond_form_riverpod: ^0.0.1

使用

以下是一个简单的登录表单示例:

import 'package:bond_form/bond_form.dart';
import 'package:bond_form_riverpod/bond_form_riverpod.dart';
import 'package:example/features/auth/data/errors/account_not_found_error.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

// 定义一个表单控制器
class LoginFormController extends FormStateNotifier<User, Error> {
  @override
  Map<String, FormFieldState> fields() => {
        'email': TextFieldState(
          null,
          label: 'Email',
          rules: [
            Rules.required(), // 必填
            Rules.email(), // 邮箱格式
          ],
        ),
        'password': TextFieldState(
          null,
          label: 'Password',
          rules: [
            Rules.required(), // 必填
            Rules.minLength(6), // 最小长度为6
            Rules.alphaNum(), // 只允许字母和数字
          ],
        ),
      };

  @override
  Future<String> onSubmit() async {
    // 获取表单字段的值
    final email = state.textFieldValue('email');
    final password = state.textFieldValue('password');

    // 定义POST请求的主体
    final body = {
      'email': email,
      'password': password,
    };

    // 发送POST请求以登录用户
    final response = await _bondFire
        .post&lt;UserMApiResult&gt;('/users/login')
        .body(body)
        .factory(UserMApiResult.fromJson)
        .errorFactory(ValidationError.fromJson)
        .cacheCustomKey('token', path: 'meta.token')
        .cacheCustomKey('user', path: 'data')
        .execute();

    return response.data;
  }
}

// 将表单控制器注册为Provider
final loginProvider = NotifierProvider&lt;LoginFormController, BondFormState&lt;String, Error&gt;&gt;(
  LoginFormController.new,
);

核心组件

FormStateNotifier

这是一个抽象类,用于管理表单状态,提供表单验证和提交的基本功能。它扩展了 Riverpod 的 <Notifier> 类,并混入了 <FormController> 以增强功能。状态由 <BondFormState> 实例表示,该实例封装了所有表单字段及其状态。

class MyFormStateNotifier extends FormStateNotifier&lt;String, MyError&gt; {
  // 实现必需的方法...
}
AutoDisposeFormStateNotifier

类似于 <FormStateNotifier>,但扩展了 <AutoDisposeNotifier> 以便于自动资源清理。非常适合那些需要高效使用资源的表单,特别是当它们不再处于用户的视图中时。

class MyAutoDisposeFormStateNotifier extends AutoDisposeFormStateNotifier&lt;String, MyError&gt; {
  // 实现必需的方法...
}

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

1 回复

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


当然,下面是一个关于如何在Flutter中使用bond_form_riverpod进行表单管理和状态管理的示例代码。bond_form_riverpod结合了bondriverpod库,简化了表单状态的管理。

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

dependencies:
  flutter:
    sdk: flutter
  flutter_hooks: ^0.18.0
  flutter_riverpod: ^1.0.0
  bond: ^0.14.0
  bond_form_riverpod: ^0.3.0

然后,你可以按照以下步骤创建和管理一个表单:

  1. 定义表单模型
import 'package:bond/bond.dart';

class UserForm extends StateNotifier<UserFormState> {
  UserForm() : super(UserFormState());

  void changeName(String value) {
    state = state.copyWith(name: value);
  }

  void changeEmail(String value) {
    state = state.copyWith(email: value);
  }
}

class UserFormState extends StatefulData {
  final String name;
  final String email;

  UserFormState({required this.name, required this.email});

  UserFormState copyWith({String? name, String? email}) {
    return UserFormState(
      name: name ?? this.name,
      email: email ?? this.email,
    );
  }

  @override
  List<Object?> get props => [name, email];
}
  1. 创建Provider
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'user_form.dart';

final userFormProvider = StateNotifierProvider<UserForm, UserFormState>(
  (ref) => UserForm(),
);
  1. 构建UI
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:bond_form_riverpod/bond_form_riverpod.dart';
import 'user_form.dart';

void main() {
  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Bond Form Riverpod Example')),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: UserFormScreen(),
        ),
      ),
    );
  }
}

class UserFormScreen extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final userForm = useProvider(userFormProvider.state);
    final formKey = useMemoized(() => GlobalKey<FormState>());

    return Form(
      key: formKey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          TextFormField(
            decoration: InputDecoration(labelText: 'Name'),
            validator: (value) {
              if (value == null || value.isEmpty) {
                return 'Name is required';
              }
              return null;
            },
            onSaved: (value) => context.read(userFormProvider).changeName(value!),
            initialValue: userForm.name,
          ),
          TextFormField(
            decoration: InputDecoration(labelText: 'Email'),
            validator: (value) {
              if (value == null || value.isEmpty || !value.contains('@')) {
                return 'Valid email is required';
              }
              return null;
            },
            onSaved: (value) => context.read(userFormProvider).changeEmail(value!),
            initialValue: userForm.email,
          ),
          SizedBox(height: 20),
          ElevatedButton(
            onPressed: () async {
              if (formKey.currentState!.validate()) {
                formKey.currentState!.save();
                // Handle form submission
                print('Form submitted: Name: ${userForm.name}, Email: ${userForm.email}');
              }
            },
            child: Text('Submit'),
          ),
        ],
      ),
    );
  }
}

在这个示例中,我们:

  1. 定义了一个UserForm类,它继承自StateNotifier<UserFormState>,并包含两个方法changeNamechangeEmail用于更新表单状态。
  2. 创建了一个UserFormState类,包含表单字段nameemail,以及一个copyWith方法用于生成新的状态实例。
  3. 使用StateNotifierProvider创建了一个userFormProvider,用于提供UserForm实例。
  4. 在UI中,我们使用useProvider钩子获取表单状态,并使用TextFormField创建表单字段。onSaved回调用于更新表单状态。
  5. 使用FormGlobalKey<FormState>进行表单验证和提交。

这个示例展示了如何使用bond_form_riverpod进行表单管理和状态管理。你可以根据需要扩展和修改这个示例以适应你的应用需求。

回到顶部