formz
formz copied to clipboard
Trigger validation when user clicks on submit
I have introduced Bloc and Formz for a Flutter application which I am currently doing.
What I was trying to achieve currently was a simple text field in a form that shows validation errors. I noticed that the behaviors of valid
and invalid
are working differently than one would expect.
If I have a property called fullname in a Bloc, I expect that these two would have the same behaviors:
-
state.fullName.valid
-
!state.fullName.invalid
But the results are different for both. Am I missing something here?
To Reproduce
Steps to reproduce the behavior: We can follow @felangel 's flutter_login project for a reference to this.
https://github.com/felangel/bloc/tree/master/examples/flutter_login
Here, in the widgets of the login form, we can try switching the "errorText" values to have either of the values.
-
errorText: state.username.valid ? null: 'invalid username',
-
errorText: state.username.invalid ? 'invalid username' : null,
Expected behavior
I expect that the boolean returned by valid
and invalid
would be opposites of each other, which is not the case.
Screenshots
With:
errorText: state.password.valid ? null : 'invalid password',
With:
errorText: state.password.invalid ? 'invalid password' : null,
Additional context
I have a sign up form, which has a couple of text fields, and drop downs. The issue I am having is that the when using the valid
property, the error text is being displayed to the user even before the user has entered anything (in the pure state).
When I am using the invalid
property, this issue is solved. But, unlike the flutter_login example, we have a user requirement where we don't disable the submit button. And I need to trigger the validation error texts for the text fields once the submit is pressed. I have an event which emits this validation.
emit(
state.copyWith(
status: Formz.validate(
[
state.fullName,
state.email,
state.phoneNumber,
],
),
),
);
But this does not work. It would be of tremendous help if someone could show me a resolve for this issue.
fullName.valid
and fullName.invalid
triggers validator()
, which will return the result whether it's Pure
or not.
You'd be better off doing something along the lines of
errorText: state.fullName.status == FormzInputStatus.pure ? null : state.fullName.error,
Assuming your ErrorType
is string, otherwise handle the error.
As for only triggering once the submit button is pressed, I haven't used bloc but something like this should work:
In your .bloc:
bool _canSubmit(
LoginPressed event,
Emitter<LoginState> emit,
) {
final result = Formz.validate([state.password, state.username]),
if (result == FormzStatus.valid) {
return true;
} else {
return false;
}
}
Add a bool to your state class which indicates whether to show errors, then in your textfields you can do:
errorText: state.showErrors ? 'some error' : null,
Then check in your button what the return value is before submitting.
onPressed: () => _canSubmit() ? _performSubmit() : _setStateToShowErrors(),
Hey @ praveengitsit, it has been some time, did the above explanation help your use case?
For cleanliness of issues, I am closing this one for now. If we can be of any further assistance, please fell free to open another issue.