I am new in Flutter as well as App Development, What I want to achieve is Show SnackBar after poping from alertbuilder.
I think following code will be useful for understanding my intentions
onSubmitted: (value) async {
try {
await FirebaseAuth.instance
.sendPasswordResetEmail(
email: _loginEmail);
} catch (e) {
SnackBar(
backgroundColor: Colors.pink,
content: Text(e.toString()),
duration: Duration(seconds: 5),
);
Navigator.of(context).pop();
}
SnackBar(
backgroundColor: Colors.pink,
content: Text('Email sent with a link!'),
duration: Duration(seconds: 5),
);
Navigator.of(context).pop();
},
I hope it'll solve your problem
1, You should await your showDialog at your onpressed event like this
var result = await showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return AlertDialog(
title: Text("your title")
content: Text("your content")
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context, 'success'); // here you can make a callback
},
child: Text('Okay')),]
);
},
);
2, so you can write
if(result=="success"){}
3, Then, show your SnackBar after that.
Before showing SnackBar you have to add your snackbar prop like I write below
final snackbar = SnackBar(content: Text('Your context message'));
and then you can show the snackbar with your context like this
Scaffold.of(context).showSnackBar(snackbar);
Related
I want to do the sign-in method and I face this run time error ,I don't know the reason cause it or how to solve it.
I want to checks all cases for login
my code is:
ElevatedButton(
onPressed: logIn,
child: StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
// try{
print('inside bulder method');
if (snapshot.connectionState ==
ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator());
}
if (snapshot.hasData) {
print('have account');
return home();
} else {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('Invalid email/password'),
backgroundColor: Colors.red.shade400,
margin: const EdgeInsets.fromLTRB(6, 0, 3, 0),
behavior: SnackBarBehavior.floating,
action: SnackBarAction(
label: 'Dismiss',
disabledTextColor: Colors.white,
textColor: Colors.white,
onPressed: () {},
)));
return Text('there is something error');
}
},
),)
and login method:
``Future<void> logIn() async {
print('inside login method');
if (_formKey.currentState!.validate()) {
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: emailController.text.trim(),
password: passwordController.text.trim(),
);
print('end try');
} catch (e) {
if (emailController.text.isNotEmpty &&
passwordController.text.isNotEmpty) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('Invalid email/password'),
backgroundColor: Colors.red.shade400,
margin: const EdgeInsets.fromLTRB(6, 0, 3, 0),
behavior: SnackBarBehavior.floating,
action: SnackBarAction(
label: 'Dismiss',
disabledTextColor: Colors.white,
textColor: Colors.white,
onPressed: () {},
)));
print("after check");
}
}
}
}
`
`
each textFormField is have the correct controller
and because of this problem I can't run this method correctly
I have this variable
dynamic _permission = true;
after clicked on button. I need to display sncakbar if _permission= false thats mean user has no permission to access the page else go to page.
but I faced an issue that _permission always equal true.
even if permission return false from api.
here is the code
Future<void> checkPermesssion() async {
String api_token = await getToken();
final response = await http.post(
Uri.parse(PermissionURL),
headers: {'Accept': 'application/json',
'Authorization': 'Bearer $api_token'
},
);
var permission = jsonDecode(response.body)['permission'];
setState(() {
_permission = permission;
});
}
and here is the button code
child: ElevatedButton(
onPressed: () {
checkPermesssion();
_permission ?
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => page()))
:
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'You don\'t have permession to access this page '),
behavior: SnackBarBehavior.floating,
margin: EdgeInsets.all(50),
elevation: 30,
action: SnackBarAction(
label: 'Dismiss',
disabledTextColor: Colors.white,
textColor: Colors.yellow,
onPressed: () {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
},
),
),
);
},
How can I do that please
Try this for button's code :
child: ElevatedButton(
onPressed: () async{
await checkPermesssion();
_permission ?
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => page()))
:
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'You don\'t have permession to access this page '),
behavior: SnackBarBehavior.floating,
margin: EdgeInsets.all(50),
elevation: 30,
action: SnackBarAction(
label: 'Dismiss',
disabledTextColor: Colors.white,
textColor: Colors.yellow,
onPressed: () {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
},
),
),
);
},
I can't solve this problem. I'm trying to do this step by step. When users push the button, first they gonna see AlertDialog, then the function startFilePickerBig will run. After the user chose files and is done with the startFilePickerBig function AlertDialog must close. But when I add Navigator.pop(context) after "await startFilePickerBig()" , alertdialog not working. When I remove "Navigator.pop(context)" which I wrote under the "await startFilePickerBig()", AlarmDialog works fine. How can I fix this?
OutlinedButton(
style: ButtonStyle(side: MaterialStateProperty.all(const BorderSide(width: 1.0, color: Color(0xFFF38F1D))), shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(7))), foregroundColor: MaterialStateProperty.all(const Color(0xFFF38F1D))),
onPressed: () async {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text(''),
content: const Text('Pease wait, Images loading... '),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Close')),],
);
});
await startFilePickerBig();
Navigator.pop(context);
},
child: const Text("Add Image"),
)
What I might do here is to use ProgressIndicator instead of AlertDialogBox with the help of ternary operator on the build function.
However, as per your approach, this might work:
onPressed: () async {
await startFilePickerBig();
bool result= await showDialog(context:context, builder:( BuildContext context){
return AlertDialog(
title:Text("Pease wait, Images loading..."),
actions: [
TextButton(
child: Text("Picked"),
onPressed: (){
Navigator.of(context).pop(true);
},
),
TextButton(
child: Text("Not picked"),
onPressed: (){
Navigator.of(context).pop(false);
},
),
],
);
});
if(result==true){
//Do whatever you want
Fluttertoast.showToast(
msg: 'Items picked',
toastLength: Toast.LENGTH_LONG,
backgroundColor: kPrimaryColor);
removeFromList(item);
}else{
//Your code
}
}
I am using the flutter_reactive_ble_example to connect to my Bluetooth module by modifying the file device_list.dart.
and I wonder how do I re prompt the user if password is wrong.
I'm fairly new to flutter, please do ask more details if required.
here is the code snippet that I currently have:
Flexible(
child: ListView(
children: widget.scannerState.discoveredDevices
.map(
(device) => ListTile(
title: Text(tile.name),
subtitle: Text("${tile.name}\n: ${tile.sub}"),
leading: const ConnectIcon(),
onTap: () async {
//stop the scan
widget.stopScan();
//connect to the device
await widget.deviceConn.connect(device.id);
//prompt user for password
final inputData = await showDialog(
context: context,
barrierDismissible:
false, // prevent user from closing the dialog by pressing outside the dialog
builder: (_) {
String userData = "";
return AlertDialog(
title: new Text("Enter Password"),
content: new TextField(
onChanged: (value) {
userData = value;
},
),
actions: <Widget>[
ElevatedButton(
child: Text('Ok'),
onPressed: () async {
//on press subscribe and send the password
response = await ble.subscribeToCharacteristic(characteristic);
//if data failure check, how do I reshow this showDialog??
response.listen((event) {
if(event == 1){
//if return 1, password correct
Navigator.of(context).pop(userData);
}else{
//if not reshow Dialog
//howw?
}
}
//send password
ble.writeCharacteristicWithoutResponse(characteristic, value: userData);
},
)
],
);
},
);
Navigator.of(context).pop(
inputData); // pass data back to the previous page
},
),
)
.toList(),
),
),
You can use a recursion I think, here an example
Future _showPasswordDialog(){
return showDialog(
context: context,
barrierDismissible:
false, // prevent user from closing the dialog by pressing outside the dialog
builder: (_) {
String userData = "";
return AlertDialog(
title: new Text("Enter Password"),
content: new TextField(
onChanged: (value) {
userData = value;
},
),
actions: <Widget>[
ElevatedButton(
child: Text('Ok'),
onPressed: () async {
//on press subscribe and send the password
response = await ble.subscribeToCharacteristic(characteristic);
//if data failure check, how do I reshow this showDialog??
response.listen((event) {
if(event == 1){
//if return 1, password correct
Navigator.of(context).pop(userData);
}else{
//if not reshow Dialog
//howw?
Navigator.of(context).pop();
_showPasswordDialog();
}
}
//send password
ble.writeCharacteristicWithoutResponse(characteristic, value: userData);
},
)
],
);
},
);
}
separate the the alert prompting as another function, and return user details if login success else return null.
Future<String> promptAlert(BuildContext context){
return showDialog(
context: context,
barrierDismissible:
false, // prevent user from closing the dialog by pressing outside the dialog
builder: (_) {
String userData = "";
return AlertDialog(
title: new Text("Enter Password"),
content: new TextField(
onChanged: (value) {
userData = value;
},
),
actions: <Widget>[
ElevatedButton(
child: Text('Ok'),
onPressed: () async {
//on press subscribe and send the password
response = await ble.subscribeToCharacteristic(characteristic);
//if data failure check, how do I reshow this showDialog??
response.listen((event) {
if(event == 1){
//if return 1, password correct
Navigator.of(context).pop(userData);
}else{
Navigator.of(context).pop();
}
}
//send password
ble.writeCharacteristicWithoutResponse(characteristic, value: userData);
},
)
],
);
},
);
}
and check for the returned value is not null on the ListItem onTap
bool isLogin = (await promptAlert(context)) !=null;
while(isLogin ){
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
duration: Duration(seconds: 2),
content: Text('Login Failed Try again')));
String user= await Future.delayed(
Duration(seconds: 2), () => promptAlert(context));
isLogin = user !=null;
}
If you want to show a snackbar and delayed alert,
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
duration: Duration(seconds: 2),
content: Text('Login Failed Try again'),
));
Future.delayed(
Duration(seconds: 2), () => promptAlert(context));
In flutter, I have a showDialog() with cancel and confirm button. The confirm button will trigger a call to an API. What I need is to show a "loading..." in the showDialog window after the click and once the API call is finished to show a success or failure. How can I manage this? Or should I close the window, waiting for the reply and popup a new dialog window with success or false? Thx for any help or better suggestion. Here what I have so far:
void _showAlert(String textLabel, String action, String linkId) {
showDialog(
context: context,
//barrierDismissible: false, // on external click
builder: (_) => new AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
title: new Text(
'Please confirm:',
style: TextStyle(color: Colors.deepOrange, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
content: new Text(
textLabel,
style: new TextStyle(fontSize: 20.0),
),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: new Text('CANCEL')),
new FlatButton(
onPressed: () {
_postAction(action, linkId).then((_) => setState(() {}));
Navigator.pop(context);
},
child: new Text('I CONFIRM')),
],
));
}
You can try this,this is just the idea..
class _SampleState extends State<Sample> {
bool isSuccessFromApi = false;
bool isLoading = false;
Widget popup() {
showDialog(context: context, builder: (builder) {
return AlertDialog(
content: !isSuccessFromApi ? Container(
child: Text('Are you Sure???'),
) : Container( child: isLoading ? CircularProgressIndicator() : Text('Success'),),
actions: <Widget>[
Text('Cancel'),
InkWell(child: Text('OK'), onTap: apiCall,)
],
);
});
}
void apiCall(){
setState(() {
isLoading = true;
});
//call the api
//after success or failure
setState(() {
isLoading = false;
isSuccessFromApi = true;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: popup(),
);
}
}