Reputation: 15
I'm trying to add user input from the alert dialog to list view. Every time I run it, the alert dialog accepts input and the item list gets updated but the list view wont update. The state of the app wont change after I press OK on the alert dialog button. Please help me with this issue as I'm new to flutter.
Future<String> createAlertDialog(BuildContext context) {
//promise to return string
TextEditingController customController =
TextEditingController(); //new texteditingc object
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Enter URL: "),
content: TextField(
controller: customController,
),
actions: [
MaterialButton(
elevation: 5.0,
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop(customController.text.toString());
},
)
],
);
});
}
@override
Widget build(BuildContext context) {
List item = List();
item=['HI'];
String temp;
return Scaffold(
appBar: AppBar(
title: Text("Shortie"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(
children:
item.map((element)=>Text(element)).toList(),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
createAlertDialog(context).then((onValue) {
temp=onValue;
print(temp);
});
setState(() {
item.add(temp);
print(item);
});
},
tooltip: 'Add URL',
child: Icon(Icons.add),
),
);
Upvotes: 0
Views: 2145
Reputation: 695
You could use the provider package and communicate the AlertDialog
with the ListView
by using notifyListeners()
and making the ListView
a Consumer
of the Provider data.
For more info about the package: https://pub.dev/documentation/provider/latest
Upvotes: 0
Reputation: 655
You have to call setState() in order to update a Widget if you have new information.
Try changing your showDialog()
to this:
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Enter URL: "),
content: TextField(
controller: customController,
),
actions: [
MaterialButton(
elevation: 5.0,
child: Text("OK"),
onPressed: () {
item.add(customController.text);
setState((){});
Navigator.of(context).pop();
},
)
],
);
});
That should add the element to the item
list, update the widget and then pop. The timing between refresh and popping the dialog box is near instantaneous, so that should be smooth.
Furthermore, you might want to use ListView.builder
, a class that will display a list that depends on the number of elements of the list of your choice.
With that said, changing the ListView
to this could help in the future:
child: ListView.builder(
itemCount: item.length,
itemBuilder: (context, index) {
return Text('${item.index}'),
},
),
Upvotes: 1
Reputation: 1865
You should use await
instate of then
. And make item
as class property. Your List is not updating because every time you called setState the build function rebuild and the value of item set to ['HI'] because of item=['HI']
this line.
Again when you use then function only the code inside of then function will execute when future will complete. That's why your setState called before your dialog finished.
Here I make some change of your code:
List item = List();
String temp;
Future<String> createAlertDialog(BuildContext context) {
//promise to return string
TextEditingController customController =
TextEditingController(); //new texteditingc object
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Enter URL: "),
content: TextField(
controller: customController,
),
actions: [
MaterialButton(
elevation: 5.0,
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop(customController.text.toString());
},
)
],
);
});
}
@override
void initState() {
item = ['HI'];
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Shortie"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(
children: item.map((element) => Text(element)).toList(),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
temp = await createAlertDialog(context);
setState(() {
item.add(temp);
print(item);
});
},
tooltip: 'Add URL',
child: Icon(Icons.add),
),
);
}
Upvotes: 0