如何使用流转换和块重置表单中的字段

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 重置已验证的字段?

如何使用流构建器和块模式更好地构建社交媒体应用程序

使用 React Native 提交数据后重置表单中的字段

如何从 Camunda 中的 EnumFormType 重置值?

如何使用jquery重置表单中的多个选择框?

如何重置包含任何验证错误的表单? [关闭]