Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rx.combineLatest doesn't call combiner when keyboard is up #574

Open
donpaul120 opened this issue Apr 13, 2021 · 6 comments
Open

Rx.combineLatest doesn't call combiner when keyboard is up #574

donpaul120 opened this issue Apr 13, 2021 · 6 comments
Labels

Comments

@donpaul120
Copy link

This be the most weird thing to debug... as i'm currently new to flutter

  Widget _buildMain(BuildContext context) {
    final viewModel = Provider.of<OnBoardingViewModel>(context, listen: false);
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      mainAxisSize: MainAxisSize.max,
      children: [
        Text(
          'Create Your Profile',
          style: TextStyle(
            fontWeight: FontWeight.bold,
            color: Colors.darkBlue,
            fontSize: 21,
          ),
          textAlign: TextAlign.start,
        ),
        SizedBox(height: 30),
        StreamBuilder(
            stream: viewModel.profileForm.usernameStream,
            builder: (context, snapshot) {
              return Styles.appEditText(
                  hint: 'Enter Username',
                  animateHint: true,
                  onChanged: viewModel.profileForm.onUsernameChanged,
                  errorText:
                      snapshot.hasError ? snapshot.error.toString() : null,
                  startIcon:
                      Icon(CustomFont.username_icon, color: Colors.colorFaded),
                  drawablePadding: 8);
            }),
        SizedBox(height: 16),
        StreamBuilder(
            stream: viewModel.profileForm.passwordStream,
            builder: (context, snapshot) {
              return Styles.appEditText(
                  hint: 'Password',
                  onChanged: viewModel.profileForm.onPasswordChanged,
                  errorText: snapshot.hasError ? snapshot.error.toString() : null,
                  animateHint: true,
                  drawablePadding: 4,
                  startIcon: Icon(CustomFont.password, color: Colors.colorFaded),
                  isPassword: true
              );
            }),
        SizedBox(height: 32),
        // Spacer(),
        StreamBuilder(
          stream: viewModel.profileForm.isValid,
          initialData: false,
          builder: (context, AsyncSnapshot<bool> snapshot) {
            print(snapshot.connectionState);
            print(snapshot);
            return Stack(
              children: [
                SizedBox(
                  width: double.infinity,
                  child: Styles.appButton(
                      onClick: snapshot.hasData && snapshot.data == true ? () => {} : null,
                      text: 'Continue'
                  ),
                ),
                Positioned(right: 16, top: 16, bottom: 16, child: SizedBox())
              ],
            );
          },
        ),
      ],
    );
  }
class ProfileForm with ChangeNotifier {

  final _usernameController = StreamController<String>.broadcast();
  Stream<String> get usernameStream => _usernameController.stream;

  final _passwordController = StreamController<String>.broadcast();
  Stream<String> get passwordStream => _passwordController.stream;


  void onUsernameChanged(String? text) {
    if(text == null || text.isEmpty) {
      _usernameController.sink.add("");
      _usernameController.sink.addError("Enter username");
    } else {
      _usernameController.sink.add(text);
    }
  }

  void onPasswordChanged(String? text) {
    if(text == null || text.isEmpty) {
      _passwordController.sink.add("");
      _passwordController.sink.addError("Enter password");
    } else {
      _passwordController.sink.add(text);
    }
  }

  // bool _isPasswordValid() {
  //   //check that the password is not empty
  //   //check that the password conforms to what we require
  // }

  Stream<bool> get isValid => Rx.combineLatest([usernameStream, passwordStream], (values) {
    print(values);
    return (values.elementAt(0) as String).isNotEmpty;
  });
  
}

The input fields works fine, that's username and password reacts well, however when the keyboard is up, the callback in combineLatest isn't trigger. i use cmd + K to open up the keyboard in ios simulator.

The idea is to validate both the username and password and that should determine if the button should be enabled or disabled.

I tried StreamGroup.merge([]) this works fine with keyboard visible or hidden, but the issue with stream group is i cannot access the typed value emitted.

I noticed that when the keyboard is up, the connectionState is always waiting, i'm quite getting my hands around flutter coming from android native (observables,livedata,flow etc) so i really don't know much here.

I'm using:
async: ^2.5.0
rxdart: ^0.26.0

@donpaul120
Copy link
Author

donpaul120 commented Apr 13, 2021

I'm sorry guys!!! After sharing my problem i found out the embarrassing issue!!!!

  Stream<bool> get isValid => Rx.combineLatest([usernameStream, passwordStream], (values) {
    print(values);
    return (values.elementAt(0) as String).isNotEmpty;
  });

get returns a new combined stream each time it's called! don't know why it works when the keyboard is hidden though..

@hoc081098
Copy link
Collaborator

You should store Stream in a field and can use shareValueSeed(...) to provide a value for StreamBuilder

@donpaul120
Copy link
Author

donpaul120 commented Apr 14, 2021

You should store Stream in a field and can use shareValueSeed(...) to provide a value for StreamBuilder

Thank you!... Please can you point me to the documentation of shareValueSeed, i googled it and can't seem to find anything.

@hoc081098
Copy link
Collaborator

You should store Stream in a field and can use shareValueSeed(...) to provide a value for StreamBuilder

Thank you!... Please can you point me to the documentation of shareValueSeed, i googled it and can't seem to find anything.

Just a typo 😃 I mean, shareValueSeeded(...): https://pub.dev/documentation/rxdart/latest/rx/ConnectableStreamExtensions/shareValueSeeded.html

@hoc081098
Copy link
Collaborator

hoc081098 commented Apr 14, 2021

class ProfileForm {
  final stream = Rx.combineLatest(...).shareValueSeeded(false);
  final subscription = stream.listen(null); // keep stream alive

  void dispose() => subscription.cancel();
}

StreamBuilder<bool>(
  stream: form.stream,
  initialData: form.stream.requireValue, // or stream.value,
  builder: ...
);

@donpaul120
Copy link
Author

@hoc081098 Cool, Thanks... I will try this out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants