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

问题描述 投票:0回答:1

我有一个屏幕,我想用流变换验证字段。验证数据时,必须启用提交按钮。当我提交表单时,我希望保持在同一屏幕上并重置数据。必须停用发送按钮。

验证过程正常,但是当我点击提交表单时,重置过程不起作用。

Validation test

下面是完整的代码。

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();
  }
}

(不在此代码中)我尝试使用控制器重置文本字段,它工作但提交按钮保持启用状态。

stream flutter rxdart bloc
1个回答
0
投票

这是因为您的TextField不会在StreamBuilder中监听文本值流。例如,你的_bloc.changeName是一个控制器,只能将动作发布到流中,不能监听任何值。

© www.soinside.com 2019 - 2024. All rights reserved.