Reputation: 53
I have a login screen with firebase authentication and error validation. When a user inserts their credentials, firebase does validation and returns error code. I am translating the error then displaying it on a snack bar. My issue is on clicking of the login button, I want the progress indicator to come up and if there are any errors caught, it must stop and only the snack bar must show. My code is as follows
myButtonOnPressed: () async {
try {
final newUser = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
if (newUser != null) {
Navigator.pushNamed(context, HomeScreen.id);
}
} on FirebaseAuthException catch (e) {
///look for error conde in switch statement and return
///english error code
String fireBaseAuthErrorCode = funcFireBaseAuthErrors(e.code);
ScaffoldMessenger.of(context).showSnackBar(
///add SnackBar function
funcSnackBar(
errorMessage: fireBaseAuthErrorCode,
snackBarColor: Color(snackBarColor),
snackBarTextColor: Color(snackBarTextColor),
snackBarTextFont: snackBarTextFont,
snackBarTextSize: snackBarTextSize,
showErrorDuration: kLoginScreenSnackBarDisplayDuration,
),
);
}
},
How on earth do I do this?
Upvotes: 0
Views: 190
Reputation: 747
I am assuming that you are using a StatefulWidget
- using which this can be achieved with a boolean variable and conditional rendering in the button.
class YourWidget extends StatefulWidget {
const YourWidget({Key? key}) : super(key: key);
@override
State<YourWidget> createState() => _YourWidgetState();
}
class _YourWidgetState extends State<YourWidget> {
bool authInProgress = false;
Future<void> login() async {
try {
// Initiate login by setting authInProgress to true.
setState(() {
authInProgress = true;
});
final newUser = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
if (newUser != null) {
Navigator.pushNamed(context, HomeScreen.id);
}
} on FirebaseAuthException catch (e) {
///look for error conde in switch statement and return
///english error code
String fireBaseAuthErrorCode = funcFireBaseAuthErrors(e.code);
ScaffoldMessenger.of(context).showSnackBar(
///add SnackBar function
funcSnackBar(
errorMessage: fireBaseAuthErrorCode,
snackBarColor: Color(snackBarColor),
snackBarTextColor: Color(snackBarTextColor),
snackBarTextFont: snackBarTextFont,
snackBarTextSize: snackBarTextSize,
showErrorDuration: kLoginScreenSnackBarDisplayDuration,
),
);
} finally {
// Regardless of the outcome, after the process is done,
// set authInProgress to false.
setState(() {
authInProgress = false;
});
}
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: login,
child: authInProgress
? const CircularProgressIndicator()
: const Text("Login"),
);
}
}
Explanation
authInProgress
with initial value of false
, indicating that process has not yet begun.setState
method set the authInProgress
to true
in the try
block, and add a finally
block, set it back to false
. The finally
block will execute regardless of the outcome in the try
block. So, in this case - whether login fails or succeeds, finally block is always executed.ElevatedButton
for this case, in which, if authInProgress
is true
, we will render CircularProgressIndicator()
, else the Text()
, that you want to display.P.S.
login()
outside of build()
for the sake of brevity.Upvotes: 1