如何使用流转换和块重置表单中的字段
Posted
技术标签:
【中文标题】如何使用流转换和块重置表单中的字段【英文标题】:How to reset fields in form with stream transform and bloc 【发布时间】:2019-07-21 06:25:53 【问题描述】:我有一个屏幕,我想通过流转换验证字段。验证数据后,必须启用提交按钮。当我提交表单时,我想留在同一个屏幕上并重置数据。必须停用发送按钮。
验证过程正常,但是当我点击提交表单时,重置过程不起作用。
下面是完整的代码。
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'TextField Test',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
class HomePage extends StatefulWidget
@override
_HomePageState createState() => _HomePageState();
class _HomePageState extends State<HomePage>
ApplicationBloc _bloc;
@override
void initState()
super.initState();
_bloc = new ApplicationBloc();
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
title: Text('FieldText Test'),
),
body: ListView(
shrinkWrap: true,
children: <Widget>[
_buildName(_bloc),
_buildEmail(_bloc),
_buildSubmit(_bloc)
],
),
);
Widget _buildName(ApplicationBloc _bloc)
return StreamBuilder(
stream: _bloc.name,
builder: (context, snapshot)
return TextField(
onChanged: _bloc.changeName,
keyboardType: TextInputType.text,
decoration: InputDecoration(
labelText: "Name",
errorText: snapshot.error,
),
);
,
);
Widget _buildEmail(ApplicationBloc _bloc)
return StreamBuilder(
stream: _bloc.email,
builder: (context, snapshot)
return TextField(
onChanged: _bloc.changeEmail,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: "Email",
errorText: snapshot.error,
),
);
,
);
Widget _buildSubmit(ApplicationBloc _bloc)
return StreamBuilder(
stream: _bloc.submit,
builder: (context, snapshot)
return RaisedButton(
onPressed: (!snapshot.hasData || !snapshot.data)
? null
: () => _bloc.submitForm(),
child: Text('Submit!'),
);
,
);
class ApplicationBloc
BehaviorSubject<String> _nameController = BehaviorSubject<String>();
Observable<String> get name => _nameController.stream.transform(validateName);
Function(String) get changeName => _nameController.sink.add;
BehaviorSubject<String> _emailController = BehaviorSubject<String>();
Observable<String> get email =>
_emailController.stream.transform(validateEmail);
Function(String) get changeEmail => _emailController.sink.add;
Observable<bool> get submit =>
Observable.combineLatest2(name, email, (e, e1) => true);
submitForm()
//Send to api and wait
//Reset values
_nameController.add(null);
_emailController.add(null);
final validateName =
StreamTransformer<String, String>.fromHandlers(handleData: (name, sink)
if (name != null && name.length > 4)
sink.add(name);
else
sink.addError('Invalid Name!');
);
final validateEmail =
StreamTransformer<String, String>.fromHandlers(handleData: (email, sink)
String p =
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]1,3\.[0-9]1,3\.[0-9]1,3\.[0-9]1,3\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]2,))$';
RegExp regExp = new RegExp(p);
if (email != null && email.length > 4 && regExp.hasMatch(email))
sink.add(email);
else
sink.addError('Invalid email!');
);
//dispose/close all the streams when we call dispose() method
void dispose()
_nameController.close();
_emailController.close();
(不在此代码中)我尝试使用控制器重置文本字段,它可以工作,但提交按钮仍然启用。
【问题讨论】:
【参考方案1】:这是因为您的 TextField 没有在 StreamBuilder 中侦听文本值流。 例如,您的 _bloc.changeName,是一个控制器,只能将动作发布到流中,不能监听任何值。
【讨论】:
以上是关于如何使用流转换和块重置表单中的字段的主要内容,如果未能解决你的问题,请参考以下文章
当点击事件在表单之外时,如何使用 FormStrap.IO/Bootstrap Validator 重置已验证的字段?