Использование combLatest для включения / отключения кнопки, но кнопка включается, даже если какой-то поток содержит ошибку

Хотите включить / отключить кнопку в зависимости от ввода пользователя. Если весь ввод текста соответствует определенному условию, только тогда активируйте кнопку «вставить».

Обычно кнопка активируется только в том случае, если все поля ввода верны. Но если одно или несколько неправильных, и пользователь переходит в другое поле ввода и меняет его на правильное / неправильное, кнопка становится доступной, даже если в какое-то поле введены неправильные данные. Проверить изображение:

введите описание изображения здесь

Код для блока входа:

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

person drmirk    schedule 24.05.2019    source источник
comment
Попробуйте это CombineLatestStream.combine4(firstname, lastname, username, password, (a, b, c, d) => true);   -  person erratbi    schedule 31.05.2020
comment
@erratbi Извините, дорогой, но ваше решение приводит к ошибке type 'CombineLatestStream<dynamic, bool>' is not a subtype of type 'Stream<QuerySnapshot<Object?>>?' любое предложение. Спасибо.   -  person Kamlesh    schedule 16.06.2021


Ответы (3)


попробуйте использовать подключение непрозрачности для включения кнопки и установите условие для щелчка и видимости .. вот так ..

            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)),
            ),
          ),

        ),
person Infusion Analysts    schedule 24.05.2019

Что-то подобное можно найти здесь

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

combLatest проверяет только событие. Он не заботится об ошибке, которая выходит из потока.

person saurabh singh    schedule 24.12.2019
comment
Я пробовал это решение, но ваше решение приводит к ошибке типа «CombineLatestStream‹ dynamic, bool ›» не является подтипом типа «Stream‹ QuerySnapshot ‹Object? ››?» любое предложение. Спасибо. - person Kamlesh; 16.06.2021

Я нашел решение, которое мне помогло. У меня была такая же проблема при создании формы входа.

Это мой код:


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.

person JasterV    schedule 29.01.2020