flutter - 颤振表单订阅验证器中的任何验证更改以禁用提交按钮
问题描述
如何订阅颤振表单中的任何验证更改?
当任何验证器返回“必需”字符串时,我想禁用表单提交按钮。
_formKey.currentState.validate()
我可以通过使用每个TextField.onChanged
函数中的调用更新我自己的状态对象来手动同步所有这些。然后在没有人更改 TextFields 中的任何内容时将提交设置为默认禁用。
那是我必须走的路吗?
以角度形式,我可以订阅验证更改:-P
解决方案
您可以使用flutter_form_bloc,在这个包中每个表单都是一个bloc
,因此您可以订阅任何表单更改,当然如果所有字段都有效。
要在任何字段出现验证错误时禁用按钮,您必须使用 aBlocBuilder
和FormBloc
,然后简单地使用该isValid
属性。
BlocBuilder<SimpleLoginFormBloc, FormBlocState>(
builder: (context, state) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
onPressed: state.isValid ? formBloc.submit : null,
child: Center(child: Text('LOGIN')),
),
);
},
)
flutter_form_bloc
具有其他有用的功能,例如通过轻松响应表单状态来导航的侦听器、异步验证等。阅读文档并查看示例。
这是禁用提交按钮的最小示例:
dependencies:
form_bloc: ^0.7.0
flutter_form_bloc: ^0.6.0
flutter_bloc: ^3.2.0
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
import 'package:form_bloc/form_bloc.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SimpleLoginForm(),
);
}
}
class SimpleLoginFormBloc extends FormBloc<String, String> {
final emailField = TextFieldBloc(
validators: [FieldBlocValidators.email],
);
final passwordField = TextFieldBloc(
validators: [FieldBlocValidators.requiredTextFieldBloc],
);
@override
List<FieldBloc> get fieldBlocs => [emailField, passwordField];
@override
Stream<FormBlocState<String, String>> onSubmitting() async* {
// Login logic...
// Get the fields values:
print(emailField.value);
print(passwordField.value);
await Future<void>.delayed(Duration(seconds: 2));
yield state.toSuccess();
}
}
class SimpleLoginForm extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider<SimpleLoginFormBloc>(
create: (context) => SimpleLoginFormBloc(),
child: Builder(
builder: (context) {
final formBloc = BlocProvider.of<SimpleLoginFormBloc>(context);
return Scaffold(
appBar: AppBar(title: Text('Simple login')),
body: ListView(
physics: ClampingScrollPhysics(),
children: <Widget>[
TextFieldBlocBuilder(
textFieldBloc: formBloc.emailField,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Email',
prefixIcon: Icon(Icons.email),
),
),
TextFieldBlocBuilder(
textFieldBloc: formBloc.passwordField,
suffixButton: SuffixButton.obscureText,
decoration: InputDecoration(
labelText: 'Password',
prefixIcon: Icon(Icons.lock),
),
),
BlocBuilder<SimpleLoginFormBloc, FormBlocState>(
builder: (context, state) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
onPressed: state.isValid ? formBloc.submit : null,
child: Center(child: Text('LOGIN')),
),
);
},
)
],
),
);
},
),
);
}
}
推荐阅读
- flutter - SliverList 可以在 TabBarView 中使用,反之亦然?
- python - Pandas 多列数据滚动
- docker - 戈兰码头 SDK。使用结构过滤任务列表
- python - Capturing frame from webcam, it return only 1 frame in opencv cv2.VideoCapture()
- eclipse - 404 JSP 文件未找到动态 Web 模块导入项目
- python - Pandas 根据逗号将列拆分为列。但添加到现有列
- firebase - 使用 Flutter 创建用户集合后,如何在 Firestore 中检索文档 ID
- php - 使用 Visual Studio Code 搜索/替换 Blade 中的所有 PHP 变量
- android - 为什么我的活动中的 ActionBar 下方有一个白条?
- firebase - 比较元素 Flutter/FirebaseFirestore