Flutter表单管理插件form_bloc_allenlinli的使用
Flutter表单管理插件form_bloc_allenlinli的使用
form_bloc_allenlinli
是一个用于简化表单状态管理的 Flutter 插件。它利用 BLoC 模式将表单状态与业务逻辑从用户界面中分离出来。
包信息
包名 | Pub |
---|---|
form_bloc | |
flutter_form_bloc |
特性
- 同步字段验证
- 异步字段验证
- 简易加载和初始化
- 向导/分段表单
- 提交进度
- 成功/失败响应
- 可序列化表单
- 提交错误到字段
- 动态字段
- 条件字段
- 列表字段
- 组字段
- 增删改查支持
- 美观的内置控件
示例
以下是 form_bloc_allenlinli
的基本使用示例:
import 'package:flutter/material.dart';
import 'package:form_bloc_allenlinli/form_bloc.dart';
// 定义登录表单的 Bloc
class LoginFormBloc extends FormBloc<String, String> {
// 定义邮箱字段
final email = TextFieldBloc<dynamic>(
validators: [
FieldBlocValidators.required,
FieldBlocValidators.email,
],
);
// 定义密码字段
final password = TextFieldBloc<dynamic>(
validators: [
FieldBlocValidators.required,
],
);
// 初始化表单字段
LoginFormBloc() {
addFieldBlocs(
fieldBlocs: [
email,
password,
],
);
}
// 当表单提交时调用此方法
[@override](/user/override)
void onSubmitting() {
// 打印输入的邮箱和密码值
print(email.value);
print(password.value);
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Form Bloc Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
[@override](/user/override)
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// 创建 LoginFormBloc 实例
final loginFormBloc = LoginFormBloc();
[@override](/user/override)
void dispose() {
// 在组件销毁时释放资源
loginFormBloc.dispose();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Form Bloc Example'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
// 显示表单字段
TextFieldBlocBuilder(
textFieldBloc: loginFormBloc.email,
decoration: InputDecoration(
labelText: 'Email',
prefixIcon: Icon(Icons.email),
),
),
TextFieldBlocBuilder(
textFieldBloc: loginFormBloc.password,
decoration: InputDecoration(
labelText: 'Password',
prefixIcon: Icon(Icons.lock),
suffixIcon: IconButton(
icon: Icon(loginFormBloc.password.isHidden ? Icons.visibility : Icons.visibility_off),
onPressed: () {
loginFormBloc.password.isHidden = !loginFormBloc.password.isHidden;
},
),
),
obscureText: true,
),
SizedBox(height: 20),
// 提交按钮
RaisedButton(
onPressed: () {
// 提交表单
loginFormBloc.submit();
},
child: Text('Submit'),
),
// 显示表单状态
StreamBuilder<bool>(
stream: loginFormBloc.isSubmitting,
initialData: false,
builder: (context, snapshot) {
return Visibility(
visible: snapshot.data,
child: CircularProgressIndicator(),
);
},
),
// 显示提交结果
StreamBuilder(
stream: loginFormBloc.submissionStatus,
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data is SubmissionSuccess) {
return Text('Success');
} else if (snapshot.hasData && snapshot.data is SubmissionFailure) {
return Text('Failed');
}
return Container();
},
),
],
),
),
);
}
}
更多关于Flutter表单管理插件form_bloc_allenlinli的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复
更多关于Flutter表单管理插件form_bloc_allenlinli的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 form_bloc_allenlinli
插件来管理 Flutter 表单的示例代码。这个插件允许你使用 BLoC 模式来管理表单状态,从而提高代码的可维护性和可测试性。
首先,确保你已经在 pubspec.yaml
文件中添加了 form_bloc_allenlinli
依赖:
dependencies:
flutter:
sdk: flutter
form_bloc: ^x.y.z # 替换为最新版本号
然后运行 flutter pub get
来获取依赖。
接下来,我们创建一个简单的表单示例,其中包括用户名和密码字段,并使用 form_bloc
来管理它们的状态。
1. 定义表单状态和数据模型
import 'package:form_bloc/form_bloc.dart';
// 表单字段状态
enum FormFieldStatus { initial, dirty, valid, invalid }
// 表单字段数据模型
class FormField<T> {
final String key;
T value;
FormFieldStatus status;
String? errorMessage;
FormField({required this.key, required this.value, this.status = FormFieldStatus.initial, this.errorMessage});
}
// 表单数据模型
class LoginFormData {
final String username;
final String password;
LoginFormData({required this.username, required this.password});
}
2. 创建表单 BLoC
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:form_bloc/form_bloc.dart';
import 'package:equatable/equatable.dart';
part 'login_form_event.dart';
part 'login_form_state.dart';
class LoginFormBloc extends Bloc<LoginFormEvent, LoginFormState> {
LoginFormBloc() : super(LoginFormState.initial());
[@override](/user/override)
Stream<LoginFormState> mapEventToState(LoginFormEvent event) async* {
if (event is UsernameChanged) {
yield* _mapUsernameChangedToState(event);
} else if (event is PasswordChanged) {
yield* _mapPasswordChangedToState(event);
} else if (event is Submitted) {
yield* _mapSubmittedToState(event);
}
}
Stream<LoginFormState> _mapUsernameChangedToState(UsernameChanged event) async* {
yield state.copyWith(
username: FormField(
key: 'username',
value: event.username,
status: FormFieldStatus.dirty,
errorMessage: _validateUsername(event.username),
),
);
}
Stream<LoginFormState> _mapPasswordChangedToState(PasswordChanged event) async* {
yield state.copyWith(
password: FormField(
key: 'password',
value: event.password,
status: FormFieldStatus.dirty,
errorMessage: _validatePassword(event.password),
),
);
}
Stream<LoginFormState> _mapSubmittedToState(Submitted event) async* {
if (state.isFormValid) {
yield state.copyWith(status: FormStatus.submitting);
// 在这里处理表单提交逻辑,比如调用API
await Future.delayed(Duration(seconds: 1)); // 模拟API调用
yield state.copyWith(status: FormStatus.success);
} else {
yield state.copyWith(status: FormStatus.invalid);
}
}
String? _validateUsername(String value) {
if (value.isEmpty || value.length < 3) {
return 'Username must be at least 3 characters long.';
}
return null;
}
String? _validatePassword(String value) {
if (value.isEmpty || value.length < 6) {
return 'Password must be at least 6 characters long.';
}
return null;
}
}
3. 定义事件和状态
login_form_event.dart
part of 'login_form_bloc.dart';
abstract class LoginFormEvent extends Equatable {
const LoginFormEvent();
}
class UsernameChanged extends LoginFormEvent {
final String username;
const UsernameChanged({required this.username});
[@override](/user/override)
List<Object?> get props => [username];
}
class PasswordChanged extends LoginFormEvent {
final String password;
const PasswordChanged({required this.password});
[@override](/user/override)
List<Object?> get props => [password];
}
class Submitted extends LoginFormEvent {
const Submitted();
[@override](/user/override)
List<Object?> get props => [];
}
login_form_state.dart
part of 'login_form_bloc.dart';
class LoginFormState extends Equatable {
final FormField<String> username;
final FormField<String> password;
final FormStatus status;
const LoginFormState({
required this.username,
required this.password,
this.status = FormStatus.initial,
});
LoginFormState copyWith({
FormField<String>? username,
FormField<String>? password,
FormStatus? status,
}) {
return LoginFormState(
username: username ?? this.username,
password: password ?? this.password,
status: status ?? this.status,
);
}
bool get isFormValid {
return username.status == FormFieldStatus.valid && password.status == FormFieldStatus.valid;
}
[@override](/user/override)
List<Object?> get props => [username, password, status];
}
enum FormStatus { initial, invalid, submitting, success }
4. 创建 Flutter UI
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:form_bloc_allenlinli/form_bloc_allenlinli.dart';
import 'login_form_bloc.dart';
void main() {
runApp(BlocProvider<LoginFormBloc>(
create: (context) => LoginFormBloc(),
child: MyApp(),
));
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: LoginFormScreen(),
);
}
}
class LoginFormScreen extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
final LoginFormBloc formBloc = context.read<LoginFormBloc>();
return Scaffold(
appBar: AppBar(title: Text('Login Form')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: BlocListener<LoginFormBloc, LoginFormState>(
listener: (context, state) {
if (state.status == FormStatus.success) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Login Success')));
}
},
child: FormBlocBuilder<LoginFormBloc, LoginFormState, LoginFormData>(
formBloc: formBloc,
initialData: LoginFormData(username: '', password: ''),
builder: (context, formData, state) {
return Column(
children: <Widget>[
TextFormFieldBlocBuilder<String>(
formBloc: formBloc,
fieldKey: 'username',
decoration: InputDecoration(labelText: 'Username'),
validator: (value) => state.username.errorMessage,
onChanged: (value) => context.read<LoginFormBloc>().add(UsernameChanged(username: value)),
),
TextFormFieldBlocBuilder<String>(
formBloc: formBloc,
fieldKey: 'password',
decoration: InputDecoration(labelText: 'Password', suffixIcon: IconButton(icon: Icon(Icons.visibility), onPressed: () {})),
validator: (value) => state.password.errorMessage,
onChanged: (value) => context.read<LoginFormBloc>().add(PasswordChanged(password: value)),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () => context.read<LoginFormBloc>().add(Submitted()),
child: Text('Login'),
),
],
);
},