Rxdart: CombineLatest doesn't really work out

Created on 8 Nov 2018  路  33Comments  路  Source: ReactiveX/rxdart

combineLatest2() doesn't really work out it return latest value and not merge two values to one.

Exemple:

Stream get submitValid =>
Observable.combineLatest2(email, password, (e, p) => true);

1) Enter an email value that is valid eg. "ed@" and then enter a password that is valid. My code is set to validate at length >= 5 so "qwerty" becomes valid on the 't'

2) delete the password until the field is now empty on screen and go back to the email section from there.

3) delete the email until the char before '@' to make it invalid.

4) re-enter the '@' character and hey presto the button is now enabled but the password field is showing red error message on screen and the value of it is still empty yet the button is enabled to be clicked.

Most helpful comment

@Jayprince20 Hi,

You need change ... Observable.combineLatest2 ... to ... Rx.combineLatest2 ...

All 33 comments

Hi there,

I'm not sure I completely follow what goes on with the example,
combineLatest simply takes the latest value from each given Stream, and provides those values to a Function.

In your snippet, the combineLatest2 will always yield true, as soon as both email and password have fired any values?
I'd simply run a validator inside the handler there, yielding true or false?

Hi, @frankpepermans

You have right that combineLatest provides those values to a Function. But like I understand if one of values has error it would provide true otherwise provide null. But validator inside the handler which yielding true or false work well :) That is strange that most popular exemple in the network for bloc_login method, does not fit to use in this way.

hmmm could you provide the original code of the bloc you're trying to port?

You can test this one from the flutter.io my code similar to this one. https://github.com/apatil88/FlutterDartProjects/tree/master/login_navigate_state_mgmt

Or you want my original code? Now I'm not at home and can't provide my original code to you. I can do it tomorrow if you need it.

ok gotcha,

so you add a ValidationError when the validation fails, thing is, an error won't enter on the listen handler, if you want an rx-y way of handling it, just add a doOnError handler, returning false for example.

Alternatively, add an onError handler on the listener.

It sounds like more professionally method :-) I will try it att home and I feel it will work :-)

I tried get it work in rx_way but always i get same problem doOnError not help it works in same way like snapshot.hasError tried in diference way but with combineLatest2 can't get work it, i feel need create new validator code with booleans, this why in exemple is wrong. With my English I not realy understand documentation but more exemples can't find in the network it is not much popular way for submit validation. You can close this issue, I can't accept that it is bug, just wrong code. Fixed it with global boolean.

Hey there -- I think we need to ask the original author of that example to update their code. We've actually gotten several folks who've written in with that exact same code saying it doesn't work.

I've actually got a small sample of how to create validation with Rx in a project of mine, I think I need to add it to this repo so folks have a proper reference for how to implement validation with combineLatest!

Hi @brianegan
You are right about asking the original author of that example to update their code, this code has spread from one instructor from the "Udemy" all exemple online looks like his code. This is my opinion. This code is wrong like @frankpepermans said, the combineLatest2 will always yield true, as soon as both email and password have fired any values, that mean email != password can be true. I fixed this issue in my bloc with handling data after combineLatest output with this code.

`final _email = BehaviorSubject();
final _password = BehaviorSubject();

Stream get submitValidation =>
Observable.combineLatest2(email, password, (e, p) {
if (e == _email.value && p == _password.value) {
return true;
}
return false;
});`

And it work very well and exactly, it return null be default, otherwise in action return true or false. I'm looking forward to see your sample of how to create validation with Rx, maybe your code more simpler that my :) Share your code here when you can. Thanks!

hi @brianegan could you link me to your validator example? pleaze :)

hi @iamarnas did you find a better solution to that issue, I saw many examples online and they all have that issue. I manage to fix that with your solution but I can't get the original error message from a validator/transformer and I need to provide a generic one "Invalid form"

Hi @demsey2
I have upgraded my archive files to AndroidX and latest Rxdart package. I hope you can find you answer in this source

GitHub Source code

I have tested this app and work well for me :)

Hello i go this same problem. I am using the latest RxDart version and i will like to update it.
error

@Jayprince20 Hi,

You need change ... Observable.combineLatest2 ... to ... Rx.combineLatest2 ...

Guys how does this work for you?

It does not work for me, and we have written same code.

Here is the issue:

First validation is ok
Make password field invalid
Make email field invalid again
Make email field valid
Button gets enabled (password field is still invalid)

Can someone help?

how

@Alexakis97 Have you tried my example with source code above?

yes, I made use of your _validate method for my two streams and the Stream<bool> get submit function, my output is the image above, for some reason works just the first time of validation. I played around a little bit and got the button highlighted even though one of the two streams is invalid

@Alexakis97 The function of your login button (onPressed) matches my example?

I just had snapshot.hasData ? , didn't notice your change there. Thank you @iamarnas

@Alexakis97 If you want use only snapshot.hasData then you can provide default value to your combineLatest on null return false. Maybe I need update this in the future.

@Alexakis97 Hi again. I have updated my repository with clean code, optimized ui view and fixed bug with snapshot.hasData now it work properly. And the code looks more professional 馃槑

GitHub Repository

@iamarnas Thank you, your example now works perfectly 馃槑.

What is the purpose of this statement identical(e, _emailController.value) && identical(p, _passwordController.value) ? (In my case)

@Alexakis97 It's bool function build in Dart to compare two Object. It's same as operator ==. (name == name).

@iamarnas somehow that line is connected to the validation check, how can e == _emailController.value ? the value is the typed password i asume

@Alexakis97 Can you explain a little wider?

@iamarnas sure, when I type on the two fields, the validation function is called through streams, and my typed value is the _emailController.value for the email address.

This is how we compare the two streams Stream<bool> get submitValid => Rx.combineLatest2(getEmailStream,getPasswordStream, (e,p) => _validate(e, p));

where the getEmailStream is Stream<String> get getEmailStream => _emailController.stream.transform(validateEmail);

In short, what's the purpose of e and p to be compared to the _emailController.value and _passwordController in _validate(e, p) ?

@Alexakis97

In short, what's the purpose of e and p to be compared to the _emailController.value and _passwordController in _validate(e, p) ?

You have understood it correctly. e value is result from the validation and control is user input. Then _validate(e, p) compare both values and return result.

@iamarnas still make no sense to me. Are you sure it work for you in all the cases.

@iamarnas still make no sense to me. Are you sure it work for you in all the cases.

@vimosanan93 Hi,
I have updated this source (Ops no null-safety) and I'm sure that this worked last time as aspected. Maybe rxdart have some changes.

@iamarnas Thanks, because of null-safety can't return null there. But, just throw an Error. Stream will handle it 鈽猴笍. Anyway thanks for your code. Now it's working fine.

// Control if validation not have error.
bool _validate(String e, String p) {
return identical(e, _usernameController.value) &&
identical(p, _passwordController.value)
? true
: throw (Exception());
}

Thanks, because of null-safety can't return null there.

Looks like it's time to update to the null-safety

@vimosanan93

@vimosanan93 Hi :wave:
I have updated combining latest example to null safety, maybe it can help improve your code.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AlexandreRoba picture AlexandreRoba  路  5Comments

brianegan picture brianegan  路  8Comments

smkhalsa picture smkhalsa  路  6Comments

SAGARSURI picture SAGARSURI  路  4Comments

egorikem picture egorikem  路  8Comments