I'm trying to create an app in Flutter.
When a particular button is pressed a Dialog shows up. In the dialog, the user can write to TextField. I want to use this text in the previous screen when the dialog is closed with pop().
Is there any way to do it?
try this:
showDialog(
context: context,
builder: (context) => Dialog(),
).then((result){
// use the result here
});
and in dialog pop like this:
Navigator.pop(context, result);
You can await to get data from button. also You can pass data .pop(YourValue)
onPressed: () async {
final data = await showDialog(
context: context,
builder: (context) {
final TextEditingController controller =
TextEditingController(); // this can be outside to get direct text from it
return AlertDialog(
content: TextField(
controller: controller,
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(controller.text);
},
child: Text("Close"))
],
);
},
);
if (data != null) {
//your operation
}
print(data);
},
Related
I used a dialog to prevent the backbutton pressed like following
WillPopScope(
onWillPop: () async => await onBackPressed(context:context, msg: 'back?')
Future<bool> onBackPressed(
{required BuildContext context, required String msg}) async {
bool willLeave = false;
await showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('$msg'),
actions: <Widget>[
TextButton(
child: const Text("OK"),
onPressed: () {
willLeave = true;
Navigator.of(context).pop();
},
),
TextButton(
child: const Text("No"),
onPressed: () => Navigator.of(context).pop())
]));
return willLeave;
}
By the way, when the dialog poped up, the dialog does not disappear although the button is pressed.
Does dialog disappear only the button or background screen tapped?
Can't I make it to disappear with the real back button?
Help me, please.. Thank you
I am call Navigator.push() after user press button on AlertDialog. But when user press button AlertDialog remain open and on top of new page.
How to dismiss AlertDialog after user press button?
Future<void> _showMyDialog() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Text('AlertDialog Title'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('This is a demo alert dialog.'),
Text('Would you like to approve of this message?'),
],
),
),
actions: <Widget>[
FlatButton(
child: Text('Approve'),
onPressed: () async {
await Navigator.push(
context,
MaterialPageRoute(builder: (context) => Page()),
);
Navigator.of(context).pop();
},
),
],
);
},
);
}
await _showMyDialog();
The comment saying to call pop is probably the easiest way to do this.
Another thing to consider next is if you want them to be able to stay on the same page. Here is a way to do both of these if you get beyond the => NewPage() style of navigation on your app. It's more commonly used for Drawers, of course.
Happy coding!
onTap: () {
newRouteName = "/form_check";
// if the current route is the exact location we're at (first on the stack), mark that
Navigator.popUntil(context, (route) {
if (route.settings.name == newRouteName) {
isNewRouteSameAsCurrent = true;
} else {
isNewRouteSameAsCurrent = false;
}
return true;
});
// if it isn't, go to the new route
if (!isNewRouteSameAsCurrent) {
Navigator.pushNamed(context, newRouteName);
}
// again if it is, just pop the drawer/dialog away
else {
Navigator.pop(context);
}
}
I have a method which check if the current users location is set, if not, open an alert dialog with two buttons: Cancel and Update Profile. the onPressed of the Update Profile button navigates to a second screen with a form to update users location. The issue is: if the user clicks on the Update button and update the location, on clicking back button, the first page is displayed with the alert dialog still open. Expectation: on closing the back button and on updating the location, the back button opens the first screen and refreshes the whole page, getting the new location setting.
See code: FIRST SCREEN (HOME SCREEN)
#override
void initState() {
super.initState();
getUserDetails();
}
updateProfileLocationPrompt(BuildContext context) {
Widget cancelButton = FlatButton(
child: Text("Cancel",
),
onPressed: () {
Navigator.of(context).pop(true);
},
);
Widget updateProfileButton = FlatButton(
child: Text("Update",
),
onPressed: () {
Navigator.of(context)
.push(new MaterialPageRoute(builder: (context) => SettingsScreen()));
},
);
AlertDialog alert = AlertDialog(
title: Text("Update location",
),
content: Text(
"Please Update you location",
),
actions: [
cancelButton,
updateProfileButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
getUserDetails() async {
var firebaseUser = FirebaseAuth.instance.currentUser;
DocumentSnapshot value = await FirebaseFirestore.instance
.collection(Str.USERS)
.doc(firebaseUser.uid)
.get();
if (value.data()[Str.ADDRESS].toString() == null ||
value.data()[Str.ADDRESS].toString() == "") {
return updateProfileAndLocationPrompt(context);
} else {
setState(() {
searchLocationAddress = value.data()[Str.ADDRESS].toString();//got from firebase
getItems();
});
}
return;
}
SECOND SCREEN - SETTINGS SCREEN
Normal page with textfields for updating location to the firebase.
The issue really: How do I navigate back to home screen, refresh home screen with the new data and reload the page thus not opening the dialog as the check on location once set should not open the dialog.
Currently, even if i navigate from the dialog to the second screen, the alert dialog is still open, home screen is not refreshed with new data.
Try
Widget updateProfileButton = FlatButton(
child: Text("Update",
),
onPressed: () async {
Navigator.pop(context);
await Navigator.of(context)
.push(new MaterialPageRoute(builder: (context) => SettingsScreen()));
setState((){});
},
);
If you want to dismiss the alert dialog, then you should pop from it right when they navigate to the next screen. To rebuild the home screen once you click back, you can use a callback, so once you press the back button it will fire the callback that's declared in the home screen.
Home Screen
void rebuildPage() {
setState(() {});
}
onPressed: () {
Navigator.pop(context);
Navigator.of(context)
.push(new MaterialPageRoute(builder: (context) => SettingsScreen(onPressed: rebuildPage)));
},
Settings Screen
final Function onPressed;
SettingsScreen({ this.onPressed });
AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context);
onPressed();
},
)
),
I am new with Flutter and I am having a problem. I'm using mobx. In my view I have a button and inside of this button, I am waiting for the showDialog property to change in order to show the dialog view . However, within onpress the showdialog does not work. Is there any other way to do this?
My controller
#observable
bool showDialog = false;
#action
Future callLoginService() async {
await Future.delayed(Duration(seconds: 6));
showDialog = true;
}
view
Observer(
builder: (_) {
return Center(
child: RaisedButton(
child: Text("TESTE"),
onPressed: () async {
controller.callLoginService();
if (controller.showDialog) {
final action = await InfoDialogView.showAlertDialog(
context, "Try again", 'Invalid user');
if (action == DialogAction.abort) {
controller.showDialog = false;
}
}
},
),
);
},
),
This is because your onPressed method is asynchronous but you haven't used 'await' keyword ahead of controller.callLoginService().
Observer(
builder: (_) {
return Center(
child: RaisedButton(
child: Text("TESTE"),
onPressed: () async {
await controller.callLoginService(); //put await for calling asynchronous methods
if (controller.showDialog) {
final action = await InfoDialogView.showAlertDialog(
context, "Try again", 'Invalid user');
if (action == DialogAction.abort) {
controller.showDialog = false;
}
}
},
),
);
},
),
I'm having a problem calling Navigator.of(context).pop() on my onPressed property in SimpleDialogOption widget. I need to set the state and dismiss the dialog. But calling setState is preventing my dialog to close. Without setState the dialog closes. Here is my dialog
WidgetsBinding.instance.addPostFrameCallback((_) {
showDialog(
builder: (BuildContext context) {
return SimpleDialog(
children: _children(suburbs),
backgroundColor: Colors.white,
title: Text('Pick your suburb'),
);
},
context: context);
});
and the method I use for the list of the Dialog:
List<Widget> _children(List<Suburb> suburbs) {
return suburbs
.map((suburb) => SimpleDialogOption(
onPressed: () {
print('#####################');
setState(() {
postcode = suburb.name;
});
Navigator.of(context).pop();
},
child: Text(suburb.name)))
.toList();
}
you can await until the return value comes from the navigator.pop,
and then call a setState
WidgetsBinding.instance.addPostFrameCallback((_) async {
postcode = await showDialog(
builder: (BuildContext context) {
return SimpleDialog(
children: _children(suburbs),
backgroundColor: Colors.white,
title: Text('Pick your suburb'),
);
},
context: context);
setState(() {
postcode;
});
});
List<Widget> _children(List<Suburb> suburbs) {
return suburbs
.map((suburb) => SimpleDialogOption(
onPressed: () {
print('#####################');
Navigator.of(context).pop(suburb.name);
},
child: Text(suburb.name)))
.toList();
}