I've created a login screen and once the email and password got verified user will be pushed to the dashboard. So what I need to do is, show a loading indicator only if there are no exceptions that get thrown otherwise it should show the alert which I've implemented with in a try-catch.
log-in button -
SizedBox(
width: MediaQuery.of(context).size.width,
child: TextButton(
onPressed: signIn,
style: ButtonStyle(
padding: MaterialStateProperty.all<EdgeInsets>(
const EdgeInsets.fromLTRB(0, 20, 0, 20),
),
shape:
MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0))),
backgroundColor:
MaterialStateProperty.all(primaryColor),
),
child: const Text(
'Login',
style: TextStyle(
color: Colors.white,
fontSize: 15,
fontFamily: 'InterBold',
),
),
),
),
Validation class -
Future signIn() async {
if (_key.currentState!.validate()) {
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: emailController.text.trim(),
password: passwordCrontroller.text.trim());
errorMessage = '';
} on FirebaseAuthException catch (e) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text(
'Error',
style: TextStyle(color: mainText),
),
content: Text(
e.message!,
style: const TextStyle(color: secondaryText),
),
contentPadding:
const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0.0),
backgroundColor: Colors.white,
actions: [
TextButton(
onPressed: () {
navigatorKey.currentState!.pop();
},
child: const Text(
'Close',
style: TextStyle(color: primaryColor),
))
],
));
}
}
}
String? validateEmail(String? formEmail) {
String pattern = r'\w @\w \.\w ';
RegExp regex = RegExp(pattern);
if (formEmail == null || formEmail.isEmpty || !regex.hasMatch(formEmail)) {
return '';
}
return null;
}
String? validatePassword(String? formPassword) {
String pattern =
r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!@#\$&*~]).{6,}$';
RegExp regex = RegExp(pattern);
if (formPassword == null ||
formPassword.isEmpty ||
!regex.hasMatch(formPassword)) {
return '';
}
return null;
}
}
Loading indicator -
showLoadingIndicatorDialog(BuildContext context) {
return showDialog(
context: context,
barrierDismissible: false,
builder: (context) => const Center(
child: CircularProgressIndicator(
color: primaryColor,
),
));
}
CodePudding user response:
So what you can do is the following :
declare the bool value _isLoading =false;
you can use the setstate to change the state.
So what does the below code do:
- Initially _isLoading will be false so it will show you the text widget.
- when you hit the signin button it will make it true so the circular progress indicator will be appearing.
- then when the api call is complete then resetting it back to false and that we can see the text widget.
- And if there comes any error en the exception making the _isLoading to false so that it will be the text widget and there will be dialog shown with error message.
I have taken your code and just made the changes check the use of bool value and use it as per you state management needs, I have elaborated with a simple setState.
class App extends StatelessWidget {
bool _isLoading =false;
@override
Widget build(BuildContext context) {
// TODO: implement build
return SizedBox(
width: MediaQuery.of(context).size.width,
child: TextButton(
onPressed: signIn,
style: ButtonStyle(
padding: MaterialStateProperty.all<EdgeInsets>(
const EdgeInsets.fromLTRB(0, 20, 0, 20),
),
shape:
MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0))),
// backgroundColor:
// MaterialStateProperty.all(primaryColor),
),
child:
_isLoading ?
const CircularProgressIndicator():
const Text(
'Login',
style: TextStyle(
color: Colors.white,
fontSize: 15,
fontFamily: 'InterBold',
),
),
),
);
}
Future signIn() async {
if (_key.currentState!.validate()) {
try {
setState({
_isLoading =true;
});
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: emailController.text.trim(),
password: passwordCrontroller.text.trim());
errorMessage = '';
setState({
_isLoading =false;
});
} on FirebaseAuthException catch (e) {
setState({
_isLoading =false;
});
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text(
'Error',
style: TextStyle(color: mainText),
),
content: Text(
e.message!,
style: const TextStyle(color: secondaryText),
),
contentPadding:
const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0.0),
backgroundColor: Colors.white,
actions: [
TextButton(
onPressed: () {
navigatorKey.currentState!.pop();
},
child: const Text(
'Close',
style: TextStyle(color: primaryColor),
))
],
));
}
}
}
}
Let me know if it works