combineLatest2() doesn't really work out it return latest value and not merge two values to one.
Exemple:
Stream
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.
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
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
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.
@Jayprince20 Hi,
You need change ... Observable.combineLatest2 ... to ... Rx.combineLatest2 ...
@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?
@Alexakis97 Trying check out my example: https://github.com/hoc081098/flutter_validation_login_form_BLoC_pattern_RxDart
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 馃槑
@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
eandpto be compared to the_emailController.valueand_passwordControllerin_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.
Most helpful comment
@Jayprince20 Hi,
You need change
... Observable.combineLatest2 ...to... Rx.combineLatest2 ...