So I am facing this problem that my alert Dialog isn't displaying. I had tried every possible solution and searching here and there but nothing works. When I click on the edit button from the pop up menu nothing is displayed everything remains the same.
Calling alert Dialog
trailing: PopupMenuButton(
icon: Icon(Icons.more_vert),
itemBuilder: (context)=>[
PopupMenuItem(
value:1,
onTap: (){
//debugPrint('popup');
Navigator.pop(context);
_showMyDialog();
},
child: ListTile(
leading: Icon(Icons.edit),
title: Text('Edit'),
)),
PopupMenuItem(
value:1,
// onTap: (){
// Navigator.pop(context);
// showDialogBox();
// },
child: ListTile(
leading: Icon(Icons.delete),
title: Text('Delete'),
)),
]),
Alert Dialog Code
Future<void> showDialogBox(String title)async{
editController.text=title;
debugPrint('dialog');
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context){
debugPrint('alert');
return AlertDialog(
title: Text('Update'),
content: Container(
child: TextFormField(
controller: editController,
),
),
actions: [
TextButton(onPressed: (){
Navigator.pop(context);
}, child: Text('Update')),
TextButton(onPressed: (){
Navigator.pop(context);
}, child: Text('Cancel')),
],
);
}
);
}
Complete Class Code
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';
import 'package:firebase_tutorial/utils/routes/routes_names.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:firebase_database/firebase_database.dart';
import '../../utils/utils.dart';
class PostScreen extends StatefulWidget {
const PostScreen({Key? key}) : super(key: key);
#override
State<PostScreen> createState() => _PostScreenState();
}
class _PostScreenState extends State<PostScreen> {
final ref=FirebaseDatabase.instance.ref('Post');
FirebaseAuth _auth=FirebaseAuth.instance;
final searchController=TextEditingController();
final editController=TextEditingController();
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: ()async{
SystemNavigator.pop();
return true;
},
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Text('Post Screen'),
actions: [
GestureDetector(
onTap: (){
_auth.signOut().then((value){
Navigator.pushNamed(context, RoutesNames.loginScreen);
}).onError((error, stackTrace){
Utils().toastMessage(error.toString());
});
},
child: Icon(Icons.logout_outlined)),
SizedBox(width: 10,),
],
),
floatingActionButton: FloatingActionButton(
onPressed:(){
Navigator.pushNamed(context, RoutesNames.newPost);
},
child: Icon(Icons.add),),
body: Column(
children: [
// Expanded(
// child:FirebaseAnimatedList(
// query: ref,
// itemBuilder: (context,snapshot,animation,index){
// return ListTile(
// title: Text(snapshot.child('post').value.toString()),
// );
// }
// ),
// ),
Padding(
padding: const EdgeInsets.all(10.0),
child: TextFormField(
onChanged: (String value){
setState(() {
});
},
controller: searchController,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: "Search",
),
),
),
Expanded(child: StreamBuilder(
stream: ref.onValue,
builder: (context,AsyncSnapshot<DatabaseEvent> snapshot){
if(!snapshot.hasData){
return CircularProgressIndicator();
}
else{
return ListView.builder(
itemCount: snapshot.data!.snapshot.children.length,
itemBuilder: (context,index){
Map<dynamic,dynamic> map=snapshot.data!.snapshot.value as dynamic;
List<dynamic> list=[];
list.clear();
list=map.values.toList();
final title=list[index]['post'].toString();
if(searchController.text.isEmpty){
return ListTile(
title: Text(list[index]['post']),
subtitle: Text(list[index]['id'].toString()),
trailing: PopupMenuButton(
icon: Icon(Icons.more_vert),
itemBuilder: (context)=>[
PopupMenuItem(
value:1,
onTap: (){
//debugPrint('popup');
Navigator.pop(context);
_showMyDialog();
},
child: ListTile(
leading: Icon(Icons.edit),
title: Text('Edit'),
)),
PopupMenuItem(
value:1,
// onTap: (){
// Navigator.pop(context);
// showDialogBox();
// },
child: ListTile(
leading: Icon(Icons.delete),
title: Text('Delete'),
)),
]),
);
}
else if(title.toLowerCase().contains(searchController.text.toLowerCase())){
return ListTile(
title: Text(list[index]['post']),
subtitle: Text(list[index]['id'].toString()),
);
}
else{
return Container();
}
});
}
}))
],
),
),
);
}
Future<void> showDialogBox(String title)async{
editController.text=title;
debugPrint('dialog');
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context){
debugPrint('alert');
return AlertDialog(
title: Text('Update'),
content: Container(
child: TextFormField(
controller: editController,
),
),
actions: [
TextButton(onPressed: (){
Navigator.pop(context);
}, child: Text('Update')),
TextButton(onPressed: (){
Navigator.pop(context);
}, child: Text('Cancel')),
],
);
}
);
}
}
try adding a delay before calling showDialog like this:
await Future.delayed(const Duration(milliseconds: 10));
Your dialog isnt displayed because when you select a menu item the pop() method is automatically called to close the popup menu; so if you open a dialog immediately, the dialog will get automatically popped.
hope this fixes your issue
I have an alertDialog containing a DropdownButton widget. Whenever I click on an option within the dropDown I want it to display the selected value. I have listed the code below along with 2 screenshots.
I believe this may be an issue with how flutter builds widget because when I placed the DropdownButton widget outside of the dialog it worked, however placing it within an alertDialog causes it to fail. I also noticed that if I clicked on an option in the DropdownButton and then exited and clicked on the dialog again the selected item would change. However, I want the selected value to change without the user having to tap out of the dialog and then back in.
^
The above image is the dialog when a user first clicks on it. At first the only selected item is "I'm not able to help". This value should change whenever a user clicks on the DropdownMenu widget and selects a different option such as "other".
^
These are the various options a user can click on within the dropdown menu. When a user clicks on it, the menu should update accordingly.
CODE:
Please note that I have defined _chosenValue as a global variable outside of the build function.
void _showDecline() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Decline Appointment Request"),
content: Container(
height: 100,
width: 200,
child: Column(
children: <Widget>[
new Text("Please select an option for why you declined."),
new DropdownButton<String>(
value: _chosenValue,
underline: Container(),
items: <String>['I\'m not able to help', 'Unclear description', 'Not available at set date and time', 'Other'].map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value, style: TextStyle(fontWeight: FontWeight.w500),),
);
}).toList(),
onChanged: (String value) {
setState(() {
_chosenValue = value;
});
},
)
],
),
),
actions: <Widget>[
// usually buttons at the bottom of the dialog
new FlatButton(
child: new Text("Close"),
onPressed: () {},
},
),
],
);
},
);
}
setState will only update current StatefulWidget's Widget Build function.
You should use StatefulBuilder inside showDialog.
For your case just add StatefulBuilder as a parent of your DropDown widget, and use StateSetter when you want to update the StatefulBuilder's children.
It will only update the widget tree defined under StateFulBuilder builder function.
See the full code including stateFulBuilder at DartPad code StateFulBuilderDartPad.
For more information on StatefulBuilder head over to StateFulBuilder documentation page.
import 'dart:convert';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(home: HomePage());
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String _chosenValue;
void _showDecline() {
showDialog(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return AlertDialog(
title: new Text("Decline Appointment Request"),
content:
Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
new Text("Please select an option for why you declined."),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: new DropdownButton<String>(
hint: Text('Select one option'),
value: _chosenValue,
underline: Container(),
items: <String>[
'I\'m not able to help',
'Unclear description',
'Not available at set date and time',
'Other'
].map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(
value,
style: TextStyle(fontWeight: FontWeight.w500),
),
);
}).toList(),
onChanged: (String value) {
setState(() {
_chosenValue = value;
});
},
)),
]),
actions: <Widget>[
// usually buttons at the bottom of the dialog
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
child: FlatButton(child: Text('Click'), onPressed: _showDecline),
),
),
);
}
}
Just check out the below example you have to use the statefulBuilder to change the state.
import 'dart:convert';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(home: HomePage());
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String _chosenValue;
void _showDecline() {
showDialog(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState){
return AlertDialog(
title: new Text("Decline Appointment Request"),
content: Container(
height: 100,
width: 200,
child: Column(
children: <Widget>[
new Text("Please select an option for why you declined."),
new DropdownButton<String>(
hint: Text('Select one option'),
value: _chosenValue,
underline: Container(),
items: <String>[
'I\'m not able to help',
'Unclear description',
'Not available at set date and time',
'Other'
].map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(
value,
style: TextStyle(fontWeight: FontWeight.w500),
),
);
}).toList(),
onChanged: (String value) {
setState(() {
_chosenValue = value;
});
},
)
],
),
),
actions: <Widget>[
// usually buttons at the bottom of the dialog
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
child: FlatButton(child: Text('Click'), onPressed: _showDecline),
),
),
);
}
}
Just let me know if it works.
onTap: () {
///___________________________________________________________________
// Get.defaultDialog(
// title: " وضعیت دزدگیر",
// middleText: "پیام اعلام وضعیت دزدگیر ارسال گردد؟",
// titleStyle: TextStyle(
// color: mainColor2, fontWeight: FontWeight.bold, fontSize: 16),
// middleTextStyle:
// TextStyle(color: mainColor6.withOpacity(0.9), fontSize: 15),
// );
///----------------------------------------------------------------------
// showDialog(
// context: context,
// builder: (context) => AlertDialog(
// content: Column(
// children: <Widget>[
// TextField(
// decoration: InputDecoration(
// icon: Icon(Icons.account_circle),
// labelText: 'Username',
// ),
// ),
// TextField(
// obscureText: true,
// decoration: InputDecoration(
// icon: Icon(Icons.lock),
// labelText: 'Password',
// ),
// ),
// ],
// ),
// ),
// );
///___________________________________________________________________
List<DropdownMenuItem<String>> listDrop = [];
String selected=null;
void loadData() {
listDrop.add(new DropdownMenuItem(
child: new Text("پایدار"),
value:"555",
));
listDrop.add(
new DropdownMenuItem(
child: new Text("لحظه ای"),
value:"444",
),
);
}
loadData();
Alert(
context: context,
title: "تنظیمات خروجی شماره ۱",
// desc: ".",
// image: Image.asset(
// "assets/settings.png",
// scale: 5,
// ),
content: Directionality(
textDirection: TextDirection.rtl,
child: Center(
child: Column(
children: <Widget>[
SizedBox(height: 20.0),
TextField(
keyboardType: TextInputType.text,
controller: _codeShargController,
decoration: InputDecoration(
labelText: 'نام خروجی',
hintText: '${out1.read('codeShargController')}',
),
),
SizedBox(height: 25.0),
Center(
child: DropdownButton(
underline: Container(
height: 1.5,
color: Colors.black26,
),
hint: Text("وضعیت عملکرد"),
items: listDrop,
isExpanded: true,
value: selected,
style: TextStyle(color: Colors.black, fontSize: 16),
onChanged: (newValue) {
selected = newValue;
// setState(() {});
setState(() { selected = newValue; });
},
),
),
SizedBox(height: 25.0),
],
),
),
),
// content: Column(
// children: <Widget>[
//
// SizedBox(height: 10.0),
//
// TextField(
//
// decoration: InputDecoration(
//
// icon: Icon(Icons.account_circle),
// labelText: 'Username',
// ),
// ),
// SizedBox(height: 10.0),
//
// TextField(
// obscureText: true,
// decoration: InputDecoration(
// icon: Icon(Icons.lock),
// labelText: 'Password',
// ),
// ),
// ],
// ),
buttons: [
DialogButton(
onPressed: () {
out1.write(
"codeShargController", _codeShargController.text);
Navigator.pop(context);
},
child: Text(
"ثبت",
style: TextStyle(color: Colors.white, fontSize: 20),
),
)
]).show();
///___________________________________________________________________
Try This ......
implement the alert on separate dart file and call it. that worked for me.
Important - there was used following dropdown plugin because that ui better for me...
Link - dropdown_button2: ^1.2.2
on main page call to the alert as follows.
import 'package:crmapp/pages/payment_history/payment_history_search_dialog.dart';
import 'package:flutter/material.dart';
class PaymentHistoryScreen extends StatefulWidget {
#override
_PaymentHistoryScreenState createState() => _PaymentHistoryScreenState();
}
class _PaymentHistoryScreenState extends State<PaymentHistoryScreen> {
ScrollController scrollController = new ScrollController();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
// Setting up AppBar
appBar: AppBar(
title: Text('Payment History'),
),
// Body
body: Container(
// your code here - you can use onpressed method in the body also.here I used it for floating button
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) {
return new PaymentHistorySearchDialog(); //call the alert dart
}
);
},
child: Container
(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(100)),
),
child: Icon(Icons.search_sharp, size: 32, color: Colors.white,)
)
),
);
}
then code the alert dart as follows.
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class PaymentHistorySearchDialog extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return PaymentHistorySearchDialogState();
}
}
class PaymentHistorySearchDialogState extends State<PaymentHistorySearchDialog> {
String? selectedValue;
List<String> items = [
'All',
'Completed',
'Pending',
'Rejected',
];
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return new AlertDialog(
titlePadding: EdgeInsets.only(top: 20, left: 15, right: 15, bottom: 5),
contentPadding: EdgeInsets.only(
top: 15,
left: 15,
right: 15,
bottom: 5
),
title: Text(
'Search'.toUpperCase(),
style: TextStyle(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.w600,
fontFamily: "medium",
)
),
content: Container(
width: double.infinity,
height: 220,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
DropdownButtonHideUnderline(
child: DropdownButton2(
hint: Text(
'Select Status',
style: TextStyle(
fontSize: 14,
),
),
items: items
.map((item) =>
DropdownMenuItem<String>(
value: item,
child: Text(
item,
style: const TextStyle(
fontSize: 14,
),
),
))
.toList(),
value: selectedValue,
onChanged: (value) {
setState(() {
selectedValue = value as String;
//Navigator.of(context).pop();
});
print(value);
// selectedValue = value as String;
},
buttonHeight: 30,
buttonWidth: double.infinity,
itemHeight: 40,
buttonDecoration: BoxDecoration(
// borderRadius: BorderRadius.circular(14),
border: Border(
bottom: BorderSide(width: 1, color: Colors.black38),
),
),
buttonPadding: const EdgeInsets.only(bottom: 5, top: 5),
),
)
],
),
)
);
}
}
I create Row with 2 widgets like this
Row(
children: [
new Radio(
value: 0,
groupValue: rv0,
onChanged: _handleRadioValueChange1,
),
GestureDetector(
onTap: (){ //trigger radio button },
child: Text('Tap Me')
)
],
)
So, when I tap on the text, the radio will be triggered, for example in javascript with jquery
$('#radio').click()
How to do it in dart flutter? thanks
Row(
children: [
new Radio(
value: 0,
groupValue: rv0,
onChanged: _handleRadioValueChange1,
),
GestureDetector(
onTap: (){
//trigger radio button
//you can pass any value which is the value of respective radio button
_handleRadioValueChange1(0)
},
child: Text('Tap Me')
)
],
)
or you can go for the RadioListTile widget.
if you want to select radio button value on click of your textview Then you need change groupValue of your radio button on click of your textview
SAMPLE CODE
class MyApp extends StatefulWidget {
#override
_State createState() => _State();
}
class _State extends State<MyApp> {
int _radioValue1 = 0;
void _handleRadioValueChange1(int value) {
setState(() {
_radioValue1 = value;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('RadioListTile Demo'),
),
//hit Ctrl+space in intellij to know what are the options you can use in flutter widgets
body: SingleChildScrollView(
child: Container(
padding: EdgeInsets.all(32.0),
child: Column(
children: <Widget>[
Radio(
value: 0,
groupValue: _radioValue1,
onChanged: _handleRadioValueChange1,
),
Radio(
value: 1,
groupValue: _radioValue1,
onChanged: _handleRadioValueChange1,
),
Radio(
value: 2,
groupValue: _radioValue1,
onChanged: _handleRadioValueChange1,
),
GestureDetector(
onTap: () {
setState(() {
_radioValue1 = 0;
});
},
child: Text("Select First Radio Button"),
),
GestureDetector(
onTap: () {
setState(() {
_radioValue1 = 1;
});
},
child: Text("Select Second Radio Button"),
),
GestureDetector(
onTap: () {
setState(() {
_radioValue1 = 2;
});
},
child: Text("Select Third Radio Button"),
)
],
),
),
),
);
}
}
I'm trying to get a popupmenu under a ListTile. The title displays a description, the subtitle displays the selected value with some message and the onTap opens the popupmenu in which a user can select a value.
I tried putting a DropdownButtonHideUnderline in the subtitle, but this displays an arrow and does not respond to the ListTile onTab obviously.
How can I get a popupmenu on a ListTile?
Maybe you can try PopuMenuButton,
PopupMenuButton<String>(
onSelected: (String value) {
setState(() {
_selection = value;
});
},
child: ListTile(
leading: IconButton(
icon: Icon(Icons.add_alarm),
onPressed: () {
print('Hello world');
},
),
title: Text('Title'),
subtitle: Column(
children: <Widget>[
Text('Sub title'),
Text(_selection == null ? 'Nothing selected yet' : _selection.toString()),
],
),
trailing: Icon(Icons.account_circle),
),
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
const PopupMenuItem<String>(
value: 'Value1',
child: Text('Choose value 1'),
),
const PopupMenuItem<String>(
value: 'Value2',
child: Text('Choose value 2'),
),
const PopupMenuItem<String>(
value: 'Value3',
child: Text('Choose value 3'),
),
],
)
Take a look at How to open a PopupMenuButton?
The below code works fine, I click the flat button and the alert dialog popup.
Questions:
1) But if I add the form.save, it shows error
flutter: The following NoSuchMethodError was thrown while handling a
gesture: flutter: The setter 'clientName=' was called on null.
flutter: Receiver: null flutter: Tried calling: clientName="423"
2) How to get the text input value such us: clientName..etc. I always get null. Pleas help.
class _formState extends State<form> {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
Booking booking;
#override
Widget build(BuildContext context) {
final getCourse = widget.course;
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
//title: Text('${widget.course.title}\n地址: ${widget.course.address}\nTEL: ${widget.course.tel}'),
title: Text('即日訂位'),
),
body: Container(
child: Form(
key: formKey,
child: ListView(
children: <Widget>[
ListTile(
leading: Icon(Icons.person_outline),
title: TextFormField(
initialValue: "",
onSaved: (val) => booking.clientName = val,
validator: (val) => val == "" ? val : null,
decoration: new InputDecoration(
labelText: "Name",
),
),
),
//Send or Post button
FlatButton(
textColor: Colors.blueAccent,
child: Text("OK"),
color: Colors.transparent,
onPressed: () {
_showFormDialog();
SystemChannels.textInput.invokeMethod('TextInput.hide');
},
)
],
),
),
),
);
}
void _showFormDialog() {
final FormState form = formKey.currentState;
if (form.validate()) {
//form.save();
var alert = new AlertDialog(
content: new Row(
children: <Widget>[
Text("hihi")
],
),
actions: <Widget>[
new FlatButton(
onPressed: () {
form.reset();
Navigator.pop(context);
},
child: Text("ok")),
new FlatButton(onPressed: () => Navigator.pop(context),
child: Text("cancel"))
],
);
showDialog(context: context,
builder: (_) {
return alert;
});
}
else {
var alert = new AlertDialog(
content:
new Row(
children: <Widget>[
Text("error!")
],
),
actions: <Widget>[
new FlatButton(onPressed: () => Navigator.pop(context),
child: Text("OK"))
],
);
showDialog(context: context,
builder: (_) {
return alert;
});
}
}
}
You have to initialize your Booking object first, try this:
Booking booking = new Booking();