使用CombineLatest启用/禁用按钮,但是即使某些流包含错误,按钮也会被启用

时间:2019-05-24 05:22:32

标签: dart flutter stream bloc rxdart

要根据用户输入启用/禁用按钮。如果所有文本输入均符合特定条件,则仅启用“插入”按钮。

通常,只有在所有输入字段正确的情况下,按钮才会启用。但是,如果一个或多个不正确,并且用户移至另一个输入字段,并将其更改为正确/不正确,则即使某个字段输入错误,按钮也会启用。查看图片:

enter image description here

登录集团的代码:

import 'package:rxdart/rxdart.dart';

class LoginScreenBloc {
  final _firstCtrl = BehaviorSubject<String>();
  final _lastCtrl = BehaviorSubject<String>();
  final _userNameCtrl = BehaviorSubject<String>();
  final _passwordCtrl = BehaviorSubject<String>();

  Function(String) get changeFirst => _firstCtrl.sink.add;
  Function(String) get changeLast => _lastCtrl.sink.add;
  Function(String) get changeUser => _userNameCtrl.sink.add;
  Function(String) get changePass => _passwordCtrl.sink.add;

  final fieldSize = StreamTransformer<String, String>.fromHandlers(
    handleData: (value, sink) {
      if (value.length > 3) {
        sink.add(value);
      } else {
        sink.addError("Can't be Empty!");
      }
    },
  );

  Stream<String> get firstname => _firstCtrl.stream.transform(fieldSize);
  Stream<String> get lastname => _lastCtrl.stream.transform(fieldSize);
  Stream<String> get username => _userNameCtrl.stream.transform(fieldSize);
  Stream<String> get password => _passwordCtrl.stream.transform(fieldSize);

  void insertValue() {
    print("${_firstCtrl.value}");
    print("${_lastCtrl.value}");
    print("${_userNameCtrl.value}");
    print("${_passwordCtrl.value}");
  }

  Stream<bool> get insertButton {
    return CombineLatestStream(
      [firstname, lastname, username, password],
      (values) {
        return true;
      },
    );
  }

  dispose() {
    _firstCtrl.close();
    _lastCtrl.close();
    _userNameCtrl.close();
    _passwordCtrl.close();
  }
}

按钮的代码:

Widget insertValue(BuildContext context, LoginScreenBloc bloc) {
  return StreamBuilder<Object>(
    stream: bloc.insertButton,
    builder: (context, snapshot) {
      return RaisedButton(
        child: Text("Insert"),
        onPressed: snapshot.hasData ? bloc.insertValue : null,
      );
    },
  );
}

3 个答案:

答案 0 :(得分:0)

尝试使用不透明连接来启用按钮,并为单击和可见性设置条件。.

            Container(
          child: Opacity(opacity: isValid ? 1.0 : 0.7,
            child: RaisedButton(
              color: Colors.red,
              onPressed: _loginPressed,

              child: Text('Sign In',
                  style: TextStyle(fontSize: 15.0, color: Colors.white)),
            ),
          ),

        ),

答案 1 :(得分:0)

Something Similar you can find here

    Stream<bool> get insertButton {
        return CombineLatestStream(
          [firstname, lastname, username, password],
          (values) {
            for(String i in values) {
               if(i.length < 3) return false;
            }
            return true;
          },
        );
      }

combineLatest仅检查事件。它不会处理从流中发出的错误。

答案 2 :(得分:0)

我找到了对我有用的解决方案。 构建登录表单时遇到了相同的问题。

这是我的代码:


class LoginFormManager with FormValidatorMixin {
  final _email = BehaviorSubject<String>();
  Stream<String> get email$ => _email.stream.transform(emailValidator);
  Function(String) get setEmail => _email.sink.add;

  final _password = BehaviorSubject<String>();
  Stream<String> get password$ => _password.stream.transform(passwordValidator);
  Function(String) get setPassword => _password.sink.add;

  Stream<bool> get isFormValid$ =>
      CombineLatestStream.combine2<String, String, bool>(email$, password$,
          (email, password) {
        if (email == _email.value && password == _password.value) {
          return true;
        } else
          return false;
      });

  void submit() {
    print(_email.value);
    print(_password.value);
  }

  void dispose() {
    _email.close();
    _password.close();
  }
}

主题_email和_password存储收到的最后一个值,包括错误。 仅当从用户收到的输入通过验证器时,email $和password $流才发送数据。 因此,就我而言,我只需要检查email $和password $发送的电子邮件和password $是否与_email和_password主题中存储的最后一个值匹配。