Как сбросить поля в форме с помощью Stream Transform и Bloc - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть экран, на котором я хочу проверить поля с преобразованием потока.Когда данные проверены, кнопка отправки должна быть включена.Когда я отправляю форму, я хочу остаться на том же экране и сбросить данные.Кнопка отправки должна быть деактивирована.

Процесс проверки работает, но когда я нажимаю на кнопку отправки, процесс сброса формы не работает.

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

(не в этом коде) Я попытался сбросить текстовое поле с контроллерами, оно работает, но кнопка отправки остается включенной.

1 Ответ

0 голосов
/ 28 февраля 2019

Это потому, что ваш TextField не слушает поток текстового значения в StreamBuilder.Например, ваш _bloc.changeName является контроллером, может только публиковать действие в поток, не может прослушивать какие-либо значения.

...