Flutter表单管理插件cubit_form的使用
Flutter表单管理插件cubit_form的使用
cubit_form
是一个使用 cubit
实现的简单表单管理解决方案。它可以帮助你更方便地管理和验证表单数据。本文将通过一个完整的示例来介绍如何使用 cubit_form
插件。
安装
首先,在你的 pubspec.yaml
文件中添加 cubit_form
依赖:
dependencies:
flutter:
sdk: flutter
cubit_form: ^最新版本
然后运行 flutter pub get
来安装依赖。
示例代码
以下是一个完整的示例,展示了如何使用 cubit_form
管理表单:
1. 创建表单逻辑
首先,创建一个继承自 SinglePageFormCubit
的类来管理表单字段和验证规则:
import 'dart:async';
import 'package:cubit_form/cubit_form.dart';
import 'package:flutter/material.dart';
abstract class Real extends SinglePageFormCubit {
Real() : super() {
login = FieldCubit<String>(
initialValue: 'Initial value',
validations: [
RequiredStringValidation('required'),
ValidationModel((value) => value.length < 3, 'too small'),
ValidationModel((value) => value.length > 20, 'too big'),
],
)..stream.listen((_) {
password.errorCheck();
});
password = FieldCubit<String>(
initialValue: '',
validations: [
RequiredStringValidation('required'),
ValidationModel((value) => value.length < 3, 'too small'),
ValidationModel((value) => value == login.state.value, 'same as login'),
],
);
zipCodeFormater = MaskTextInputFormatter(
initialText: '1234-123',
mask: '#####-####',
filter: {"#": RegExp(r'[0-9]')},
);
zipCode = FieldCubit(
initialValue: zipCodeFormater.getMaskedText(),
validations: [
RequiredStringValidation('Required'),
RegExpValidation(
RegExp(r'^(^\d{5}$)|(^\d{5}-\d{4}$)'),
'should be 4 or 9 digits',
),
],
);
number = FieldCubit(
initialValue: 100,
validations: [RequiredIntValidation('required')],
);
var fields = [login, password, zipCode, number];
addFields(fields);
}
late FieldCubit<String> login;
late FieldCubit<String> password;
late MaskTextInputFormatter zipCodeFormater;
late FieldCubit<String> zipCode;
late FieldCubit<int> number;
@override
FutureOr<bool> asyncValidation() {
// login.setError('here async error');
return true;
}
}
class RealChild extends Real {
RealChild() {
string = FieldCubit<String>(
initialValue: 'aaa',
validations: [
RequiredStringValidation('required'),
],
);
var fields = [string];
addFields(fields);
}
@override
void onSubmit() async {
print('===start===');
await Future.delayed(Duration(seconds: 2));
print(login.state.value);
print(password.state.value);
print(string.state.value);
for (var f in fields) {
f.reset();
}
}
void setString() {
string.externalSetValue('bbb');
}
@override
reset() {
for (var f in fields) {
f.reset();
}
}
late FieldCubit<String> string;
}
2. 创建UI
接下来,创建一个 MyApp
和 MyHomePage
来展示表单:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:cubit_form/cubit_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: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: BlocProvider<RealChild>(
create: (_) => RealChild(),
child: Builder(builder: (context) {
var formCubit = context.watch<RealChild>();
return SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 40),
child: Text('''
validation rules:
- login must be longer than 3 symbols and shorter than 10
- password must be longer than 3 symbols and not the same as login
'''),
),
Text(formCubit.login.state.value),
CubitFormTextField(
formFieldCubit: formCubit.login,
decoration: InputDecoration(
hintText: 'name',
labelText: 'login',
),
),
CubitFormIntField(
formFieldCubit: formCubit.number,
decoration: InputDecoration(
hintText: 'number',
labelText: 'count',
),
),
CubitFormTextField(
formFieldCubit: formCubit.password,
obscureText: true,
decoration: InputDecoration(
hintText: 'another text',
labelText: 'password',
),
),
CubitFormMaskedTextField(
formFieldCubit: formCubit.zipCode,
decoration: InputDecoration(
labelText: 'zipCode', helperText: 'zipCode'),
maskFormatter: formCubit.zipCodeFormater,
),
CubitFormTextField(
cursorColor: Colors.red,
formFieldCubit: formCubit.string,
decoration: InputDecoration(
hintText: 'another string',
labelText: 'string',
suffixIcon: Padding(
padding: const EdgeInsets.only(right: 8),
child: IconButton(
icon: Icon(
Icons.refresh,
),
onPressed: () => formCubit.setString(),
),
),
),
),
if (formCubit.state.hasErrorToShow)
Center(
child: _Error(
child: Text('Not valid'),
),
),
Text(formCubit.state.isInitial ? "initial" : 'changed'),
if (!formCubit.state.hasErrorToShow)
Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(
child: Text(formCubit.state.isSubmitting
? 'Submitting'
: 'Submit'),
onPressed: formCubit.state.isSubmitting
? null
: () => formCubit.trySubmit(),
),
ElevatedButton(
child: Text('Reset'),
onPressed: () => formCubit.reset(),
),
],
),
)
],
),
);
}),
),
),
);
}
}
class _Error extends StatelessWidget {
const _Error({
Key? key,
required this.child,
}) : super(key: key);
final Widget child;
@override
Widget build(BuildContext context) {
return Material(
elevation: 2,
child: Container(
constraints: BoxConstraints(minWidth: 88.0, minHeight: 36.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
color: Colors.red,
),
child: Center(
widthFactor: 1.0,
heightFactor: 1.0,
child: child,
),
),
);
}
}
3. 运行应用
现在,你可以运行你的 Flutter 应用程序来查看表单管理的效果。确保所有依赖项都已正确安装,并且没有语法错误。
flutter run
总结
通过上述示例,你可以看到 cubit_form
插件如何帮助你管理和验证表单数据。它提供了丰富的功能,如字段验证、异步验证、字段重置等,使得表单管理变得更加简单和高效。希望这个示例对你有所帮助!如果你有任何问题或建议,欢迎在评论区留言。
更多关于Flutter表单管理插件cubit_form的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter表单管理插件cubit_form的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter中使用cubit_form
插件进行表单管理的代码示例。cubit_form
是一个用于处理Flutter表单状态的Cubit库,它使得状态管理和表单验证变得更加简单。
首先,确保你已经在pubspec.yaml
文件中添加了cubit_form
和flutter_bloc
的依赖:
dependencies:
flutter:
sdk: flutter
flutter_bloc: ^8.0.0 # 请使用最新版本
cubit_form: ^0.1.0 # 请使用最新版本,注意版本号可能有所不同
然后,运行flutter pub get
来安装这些依赖。
接下来,我们将创建一个简单的登录表单示例,其中包括用户名和密码字段,以及提交按钮。
1. 定义表单状态
首先,我们需要定义一个表单状态类,它将包含我们的表单字段和验证规则。
import 'package:cubit_form/cubit_form.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
part 'login_form_state.dart';
class LoginFormCubit extends Cubit<FormState<LoginFormState>> {
LoginFormCubit() : super(FormState<LoginFormState>(LoginFormState()));
void usernameChanged(String value) {
emit(state.copyWith(
username: FormFieldState<String>(value: value, validators: [requiredValidator]),
));
}
void passwordChanged(String value) {
emit(state.copyWith(
password: FormFieldState<String>(value: value, validators: [requiredValidator, minLengthValidator(6)]),
));
}
void submitted() {
emit(state.copyWith(
status: FormStatus.submitting,
));
final isValid = state.validate();
if (isValid) {
// Handle successful submission
emit(state.copyWith(status: FormStatus.submitted));
} else {
emit(state.copyWith(status: FormStatus.error));
}
}
}
在上面的代码中,我们定义了一个LoginFormCubit
,它继承自Cubit
并持有FormState<LoginFormState>
作为状态。LoginFormState
类定义表单字段的状态,这里我们定义了username
和password
字段,并为它们设置了验证规则。
2. 定义表单字段状态
接下来,我们定义LoginFormState
类,它将包含表单字段的状态。
// login_form_state.dart
part of 'login_form_cubit.dart';
class LoginFormState {
final FormFieldState<String> username;
final FormFieldState<String> password;
LoginFormState({
required this.username,
required this.password,
});
LoginFormState copyWith({
FormFieldState<String>? username,
FormFieldState<String>? password,
}) {
return LoginFormState(
username: username ?? this.username,
password: password ?? this.password,
);
}
}
3. UI 层
最后,我们在UI层使用BlocBuilder
和BlocProvider
来连接我们的Cubit和UI组件。
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'login_form_cubit.dart';
void main() {
runApp(MultiBlocProvider(
providers: [
BlocProvider(create: (_) => LoginFormCubit()),
],
child: MyApp(),
));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: LoginScreen(),
);
}
}
class LoginScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Login')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: BlocListener<LoginFormCubit, FormState<LoginFormState>>(
listener: (context, state) {
if (state.status == FormStatus.submitted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Login Successful')));
} else if (state.status == FormStatus.error) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Please fix the errors')));
}
},
child: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(labelText: 'Username'),
onChanged: (value) => context.read<LoginFormCubit>().usernameChanged(value),
controller: TextEditingController(text: state.username.value), // 需要手动管理控制器以显示当前值
),
TextField(
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
onChanged: (value) => context.read<LoginFormCubit>().passwordChanged(value),
controller: TextEditingController(text: state.password.value), // 需要手动管理控制器以显示当前值
),
SizedBox(height: 24),
ElevatedButton(
onPressed: () => context.read<LoginFormCubit>().submitted(),
child: Text('Login'),
),
],
),
),
),
);
}
}
注意:由于TextField
的controller
属性在cubit_form
的使用中并不是直接支持的,上面的代码示例中手动管理了TextEditingController
来显示当前值,但在实际使用中,你可能需要找到一种方法来同步cubit
状态和TextField
的显示,这通常涉及到在表单状态改变时更新控制器,以及在控制器内容改变时更新cubit状态。这可以通过监听控制器的变化或在需要时手动同步状态来实现。
这个示例展示了如何使用cubit_form
库进行基本的表单管理和验证。根据你的具体需求,你可能需要调整状态管理和验证逻辑。