User Input to Fetch data from API in Flutter - function

I need to fetch data from an API by taking an User Input number. When an user types a number in the txt form field, it generates the fact for that number.
API I used is NumbersApi.
This is my function for fetching data -
String fact;
int number;
void userInputForTrivia() async {
http.Response response;
response = await http.get(Uri.http('numbersapi.com', '$number/trivia'));
if (response.statusCode == 200) {
print(response.statusCode);
print(response.body);
setState(() {
fact = response.body;
});
}
}
#override
void initState() {
userInputForTrivia();
super.initState();
}
Following is the code for Text form filled-
AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0)),
title: Text('Enter your lucky number'),
content: TextFormField(
cursorColor: Colors.purple[400],
keyboardType: TextInputType.number,
controller: _textFieldController,
autofocus: true,
decoration: InputDecoration(hintText: "Enter any number"),
),
actions: [
ElevatedButton(
onPressed: () {
userInputForTrivia();
},
child: Text("OK"),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.purple[400]),
),
)
],
);
This is the txt widget-
Text(fact.toString(),
style: TextStyle(
fontSize: 20.0,
color: Colors.purple[400],
)),
Whenever user presses a button an alert dialog box is popped up in which user needs to type a number to generate a fact for that number.
But whenever I type a number its not showing the fact, what am I missing?
Any help will be much appreciated :)

add onChanged method
TextFormField(
//.... rest of the code ......
onChanged: (value) {
number = int.parse(value);
},
//.... rest of the code ......
),

Related

API give data NULL in first Load

I get the data from API and when API calls on the first load of the screen so API gets the data but in response, the data shows the null value, and when I click on hot reload it response shows data from API.
I don't know what happens with API or response.
Please someone help me to understand what happened with the response I also used await but nothing happens.
Here is my code:-
import 'package:flutter/material.dart';
import 'package:mindmatch/utils/widget_functions.dart';
import 'package:mindmatch/screens/Favorites.dart';
import 'package:mindmatch/screens/Editprofile.dart';
import 'package:getwidget/getwidget.dart';
import 'package:mindmatch/screens/Sidebar.dart';
import 'package:mindmatch/screens/Footer.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:mindmatch/utils/Auth.dart';
class Profile extends StatefulWidget {
var usrid;
Profile({Key? key, #required this.usrid}) : super(key: key);
#override
_Profile createState() => _Profile();
}
class _Profile extends State<Profile>{
//SingingCharacter? _character = SingingCharacter.male;
var url;
var data;
final body = null;
#override
Widget build(BuildContext context){
var UsrID = widget.usrid;
final Size size = MediaQuery.of(context).size;
final ThemeData themeData = Theme.of(context);
final double padding = 25;
final sidePadding = EdgeInsets.symmetric(horizontal: padding);
var url = Uri.https('www.******.net', '/mm_api/index.php',{'act':'profile','UsrID': UsrID});
print(url);
// print(getData());
Future getData() async{
final res = await http.get(
url,
headers: {'Content-Type': 'application/json'},
);
//var res = await http.get(Uri.parse('www.*******.net/mm_api/index.php?act=profile&UsrID=${UsrID}'));
print(res);
//data = json.decode(res.body);
data = jsonDecode(res.body);
print(data);
//setState(() {});
//print(res.body);
}
#override
void initState() async{
super.initState();
getData();
// print (await getData());
}
print(data);
//print(getData());
//return SafeArea(
return Scaffold(
appBar: AppBar(
titleSpacing: 3,
backgroundColor: Colors.white,
elevation: 0,
title: Text('My Profile', style: TextStyle(color: Colors.black, fontSize: 15,),),
leading: Builder(
builder: (BuildContext context) {
return Padding(padding: EdgeInsets.fromLTRB(15, 0, 0, 0),
child: IconButton(
icon: SvgPicture.asset(
width: 30,
'assets/images/Menu.svg',
height: 30,
),
onPressed: () { Scaffold.of(context).openDrawer(); },
tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
),
);
},
),
actions: <Widget>[
Padding(
padding: sidePadding,
child: Row(
children: [
//Icon(Icons.search, color: Colors.black,),
SvgPicture.asset(
width: 30,
'assets/images/search.svg',
height: 30,
),
],
)
)
],
),
backgroundColor: Color(0xff8f9df2),
body: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
//colors: const [Color.fromRGBO(132,105,211,1), Color.fromRGBO(93,181,233,1), Color.fromRGBO(86,129,233,1)],
colors: [Colors.white, Colors.white]
),
),
width: size.width,
height: size.height,
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//addVerticalSpace(30),
data != null?Expanded(
child: Padding(
padding: sidePadding,
child: ListView(
physics: BouncingScrollPhysics(),
children: [
Text('${data[0]['name']}')
],
),
)
): const Center(
child: CircularProgressIndicator(),
)
],
),
],
)
),
drawer: Sidebar(),
persistentFooterButtons: [
Footer(usrid:UsrID),
],
);
//);
}
}
When first load screen it shows me a null value:- Here I Print data form response but it shows me a null value
And when I hot reload the screen it shows me the response value:- It shows the value and I comment any print value or hot reload the screen
Data from API:-
[{"id":"1","name":"anni","fulname":"anni ann","mobile":"+15214639870","email":"anni#gmail.com","about":"sdhbsdbcshcbsdhcbsbchsdb\ncbhbchsc","lookfor":"Relationship, Networking","education":"gcnd,2018","work":"dhfjsk,fjskk","politics":"Liberal, Apolitical","religion":"Protestant, Anglican, Hindu","children":"Have + don't want more, Have and want more","interests":"Treking, Sports, Cooking","distance":" 17 ","age":" 20, 60 "}]
when I test API on the browser it shows correct data but does not show in response
WHY?
Please help me to understand this.
I don't know whats going on with the response
It also looks like you are calling initState in your build method. You have to move it out of build method as it is a separate override method.
You have to call setstate after catching data from api
add this line in your getdata() at the end setstate()
setstate() is used to hot reload programatically so in other words when your app update it's state or any information which is used by your app you have to call setstate() function for reflate on your app's ui.
setstate() function call build method one time again and draw whole tree again.
if you have not use setstate then i suggest some code below do this.
final res = await http.get(
url,
headers: {'Content-Type': 'application/json'},
);
//var res = await http.get(Uri.parse('www.*******.net/mm_api/index.php?act=profile&UsrID=${UsrID}'));
print(res);
//data = json.decode(res.body);
dynamic data = jsonDecode(res.body);
print(data);
return data;
//setState(() {});
//print(res.body);
}
//then edit your future builder
FutureBuilder(builder: (context, snapshot) {
if(snapshot.connectionState==ConnectionState.waiting){
//return loader
}else {
if(snapshot.hasData==true){
//update your ui
}else{
//data is null
}
}
}```

how to show Api response after login in flutter?

I successfully got responses from my API, when a user login with his/her correct or incorrect credentials. how can I display those Api responses in my app whether the user put correct /incorrect name, password?
Here is my API response if he put his correct credentials: if he put the wrong credentials the status code will be 0
Suppose I want to print Status and Message. how can I display that in my app?
Here is my function to call Api:
Future<void> login() async {
var jsonResponse = null;
if (passwordontroller.text.isNotEmpty && emailController.text.isNotEmpty) {
List user;
var response = await http.post(
Uri.parse("http://kokokokokokoklogin"),
body: ({
'LoginId': emailController.text,
'Password': passwordontroller.text
}));
if (response.statusCode == 200) {
print("Correct");
print(response.body);
print(jsonResponse);
Navigator.push(
context, MaterialPageRoute(builder: (context) => Second()));
} else {
print("Wronggooooooooooooooooooooooooooo");
print(response.body);
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Invalid credentials")));
}
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Blank field is not allowed")));
}
}
And here is my textFormField where user will put his/her credentials
TextFormField(
controller:
emailController, //==========================================
decoration: InputDecoration(
labelText: "Email",
border: OutlineInputBorder(),
suffixIcon: Icon(Icons.email)),
),
SizedBox(
height: 10,
),
TextFormField(
controller:
passwordontroller, //=========================================
obscureText: true,
decoration: InputDecoration(
labelText: "Password",
border: OutlineInputBorder(),
suffixIcon: Icon(Icons.password)),
),
SizedBox(
height: 45,
),
OutlinedButton.icon(
onPressed: () {
login();
},
SecondPage
Convert your response to JSON and get the parts like this, add error handling (for example if JSON conversion fails):
import 'dart:convert';
And where you get the response:
final jsonResponse = jsonDecode(response.body);
final status = jsonResponse["Status"];
final message = jsonResponse["Message"];
If you want to use this in secondPage, create a named route with arguments and pass it to the route, like explained in the documentation. Or even better, use a FutureBuilder to build the widget that needs the response. This way you can also display a progress indicator while login request is being processed.
Finally Manage to solve it
Here what I did
class AfterLoginResPage extends StatefulWidget {
final ApiResponse rresponse;
const AfterLoginResPage({required this.rresponse});
#override
_AfterLoginResPageState createState() => _AfterLoginResPageState();
}
class _AfterLoginResPageState extends State<AfterLoginResPage> {
var responseRef;
// _SecondState(this.responseRef);
#override
Widget build(BuildContext context) {
var tuhin = Text("Status: ${widget.rresponse.status}");
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Status: ${widget.rresponse.status}"),
Text("Message: ${widget.rresponse.message}"),
Text("Name: ${widget.rresponse.userData!.name}"),
Text("encUserId: ${widget.rresponse.userData!.encUserId}"),
// Text("name: ${widget.UserData.name}"),
SizedBox(
height: 50,
),
OutlinedButton.icon(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Home(),
),
);
},
icon: Icon(
Icons.exit_to_app,
size: 18,
),
label: Text("GoTo Home")),
],
),
),
),
);
}
}

Flutter how to save list data locally

I am building a to-do list app and I would like to store the data locally such that every time I open the app, I get all the tasks that I had created previously. I am new to flutter and this is my first app. I already tried saving the data to a file, creating a JSON file to save the data and tried using a database. Nothing seems to work. Can someone help me with this?
This is my code: -
import 'package:flutter/material.dart';
class toDoList extends StatefulWidget
{
bool data = false;
#override
createState()
{
return new toDoListState();
}
}
class toDoListState extends State<toDoList>
{
List<String> tasks = [];
List<bool> completedTasks = [];
List<String> descriptions = [];
List<bool> importance = [];
#override
Widget build(BuildContext context)
{
return new Scaffold
(
body: buildToDoList(),
floatingActionButton: new FloatingActionButton
(
onPressed: addToDoItemScreen,
tooltip: 'Add Task',
child: new Icon(Icons.add),
),
);
}
Widget buildToDoList()
{
return new ListView.builder
(
itemBuilder: (context, index)
{
if(index < tasks.length)
{
if(tasks[index] == "#45jiodg{}}{OHU&IEB")
{
tasks.removeAt(index);
descriptions.removeAt(index);
importance.removeAt(index);
}
return row(tasks[index], descriptions[index], index);
};
},
);
}
Widget row(String task, String description, int index)
{
return Dismissible(
key: UniqueKey(),
background: Container(color: Colors.red, child: Align(alignment: Alignment.center, child: Text('DELETE', textAlign: TextAlign.center, style: TextStyle(color: Colors.white, fontSize: 18),))),
direction: DismissDirection.horizontal,
onDismissed: (direction) {
setState(() {
tasks.removeAt(index);
if(completedTasks[index])
{
completedTasks.removeAt(index);
}
descriptions.removeAt(index);
importance.removeAt(index);
});
Scaffold.of(context).showSnackBar(SnackBar(content: Text(task+" dismissed")));
},
child: CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
title: Text(task, style: (completedTasks[index]) ? TextStyle(decoration: TextDecoration.lineThrough) : TextStyle(),),
subtitle: Text(descriptions[index], style: (completedTasks[index]) ? TextStyle(decoration: TextDecoration.lineThrough) : TextStyle(),),
isThreeLine: true,
secondary: (importance[index])? Icon(Icons.error, color: Colors.red,) : Text(''),
value: completedTasks[index],
onChanged: (bool value) {
setState(() {
if(completedTasks[index])
{
completedTasks[index] = false;
}
else
{
completedTasks[index] = true;
}
});
},
));
}
void addToDoItemScreen() {
int index = tasks.length;
while (importance.length > tasks.length) {
importance.removeLast();
}
importance.add(false);
tasks.add("#45jiodg{}}{OHU&IEB");
descriptions.add("No Description");
completedTasks.add(false);
Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
return StatefulBuilder(builder: (context, setState) { // this is new
return new Scaffold(
appBar: new AppBar(title: new Text('Add a new task')),
body: Form(
child: Column(
children: <Widget>[
TextField(
autofocus: true,
onSubmitted: (name) {
addToDoItem(name);
//Navigator.pop(context); // Close the add todo screen
},
decoration: new InputDecoration(
hintText: 'Enter something to do...',
contentPadding: const EdgeInsets.all(20.0),
border: OutlineInputBorder()),
),
TextField(
//autofocus: true,
//enabled: descriptions.length > desc,
onSubmitted: (val) {
addDescription(val, index);
},
decoration: new InputDecoration(
hintText: 'Enter a task decription...',
contentPadding: const EdgeInsets.all(20.0),
border: OutlineInputBorder()),
),
Row(
children: <Widget> [
Switch(
value: importance[index],
onChanged: (val) {
setState(() {
});
impTask(index);
},
),
Text('Important Task', style: TextStyle(fontSize: 18)),
],
),
RaisedButton(onPressed: () { Navigator.pop(context); }, child: Text('DONE', style: TextStyle(fontSize: 20)),)
],
),
));
});
}));
}
void addToDoItem(String task)
{
setState(() {
tasks.last = task;
});
}
void addDescription(String desc, int index)
{
setState(() {
descriptions.last = desc;
});
}
void impTask(int index)
{
setState(() {
if(importance[index])
{
importance[index] = false;
}
else
{
importance[index] = true;
}
});
}
}
I have 4 lists with the data. I need a simple way to save the lists such that the next time I open the app, the lists retain the data that was saved in them, the last time I had closed the app.
To do this you'll certainly have to use the path_provider package with this tutorial on the flutter.dev website. You should then be able to register a file and read it at the start of your application.
Once you have imported the path_provider and the dart:io packages, you can do something like this :
final directory = await getApplicationDocumentsDirectory();
final File file = File('${directory.path}/jsonObjects.json');
if (await file.exists()) {
json = await file.readAsString();
} else {
file.writeAsString(json);
}
First you get the application document directory ( the path ), then you create a File with the right path. Then if the file already exist, you read it, else you create it with the json you got and you should be good to go !

How can we use JSON with datatable?

I am new on flutter but I work a lot for learning all I need for my projects.
I have a JSON sent by a server using HTTP:
[{"equipe1":"PSG","equipe2":"DIJON","type_prono":"1N2"},{"equipe1":"MONACO","equipe2":"REIMS","type_prono":"1N2"},{"equipe1":"TOULOUSE","equipe2":"RENNES","type_prono":"1N2"},{"equipe1":"MONTPELLIER","equipe2":"STRASBOURG","type_prono":"1N2"},{"equipe1":"AMIENS","equipe2":"METZ","type_prono":"1N2"},{"equipe1":"BREST","equipe2":"ANGERS","type_prono":"1N2"},{"equipe1":"LORIENT","equipe2":"CHAMBLY","type_prono":"1N2"}]
And I try to set it to a datatable widget but it seems complicated to do.
Now here is my entire code :
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'dart:async';
// Create a Form widget.
class Affiche_grille extends StatefulWidget {
#override
Affiche_grille_State createState() {
return Affiche_grille_State();
}
}
// Create a corresponding State class.
// This class holds data related to the form.
class Affiche_grille_State extends State<Affiche_grille> {
#override
final _formKey = GlobalKey<FormState>();
Grille_display() async {
// SERVER LOGIN API URL
var url = 'http://www.axis-medias.fr/game_app/display_grid.php';
// Store all data with Param Name.
var data = {'id_grille': 1};
// Starting Web API Call.
var response = await http.post(url, body: json.encode(data));
// Getting Server response into variable.
var match = json.decode(response.body);
}
Widget build(BuildContext context) {
// Build a Form widget using the _formKey created above.
var listmatch = Grille_display();
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
DataTable(
columnSpacing: 20,
columns: [
DataColumn(
label: Text("Eq 1"),
numeric: false,
tooltip: "",
),
DataColumn(
label: Text("Eq 2"),
numeric: false,
tooltip: "",
),
DataColumn(
label: Text("Type pro"),
numeric: false,
tooltip: "",
),
],
rows: EquipeList.map((equipe_detail) => DataRow(
cells: [
DataCell(
Text(equipe_detail['equipe1'].toString()),
),
DataCell(
Text(equipe_detail['equipe2'].toString()),
),
DataCell(
Text(equipe_detail['type_prono'].toString()),
),
]),
).toList(),
)
],
)
);
}
}
class Match_detail {
String equipe1;
String equipe2;
String typeProno;
Match_detail({this.equipe1, this.equipe2, this.typeProno});
Match_detail.fromJson(Map<String, dynamic> json) {
equipe1 = json['equipe1'];
equipe2 = json['equipe2'];
typeProno = json['type_prono'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['equipe1'] = this.equipe1;
data['equipe2'] = this.equipe2;
data['type_prono'] = this.typeProno;
return data;
}
}
class EquipeList {
List<Match_detail> breeds;
EquipeList({this.breeds});
factory EquipeList.fromJson(List<dynamic> json) {
return EquipeList(
breeds: json
.map((e) => Match_detail.fromJson(e as Map<String, dynamic>))
.toList());
}
}
It doesn't work :( it says me : error: The method 'map' isn't defined for the class 'EquipeList'. (undefined_method at [flutter_app] lib
You can copy paste run full code below
You can use package https://pub.dev/packages/json_table
working demo
full code
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:json_table/json_table.dart';
class SimpleTable extends StatefulWidget {
#override
_SimpleTableState createState() => _SimpleTableState();
}
class _SimpleTableState extends State<SimpleTable> {
final String jsonSample =
'[{"equipe1":"PSG","equipe2":"DIJON","type_prono":"1N2"},{"equipe1":"MONACO","equipe2":"REIMS","type_prono":"1N2"},{"equipe1":"TOULOUSE","equipe2":"RENNES","type_prono":"1N2"},{"equipe1":"MONTPELLIER","equipe2":"STRASBOURG","type_prono":"1N2"},{"equipe1":"AMIENS","equipe2":"METZ","type_prono":"1N2"},{"equipe1":"BREST","equipe2":"ANGERS","type_prono":"1N2"},{"equipe1":"LORIENT","equipe2":"CHAMBLY","type_prono":"1N2"}]';
bool toggle = true;
#override
Widget build(BuildContext context) {
var json = jsonDecode(jsonSample);
return Scaffold(
body: Container(
padding: EdgeInsets.all(16.0),
child: toggle
? Column(
children: [
JsonTable(
json,
showColumnToggle: true,
tableHeaderBuilder: (String header) {
return Container(
padding: EdgeInsets.symmetric(
horizontal: 8.0, vertical: 4.0),
decoration: BoxDecoration(
border: Border.all(width: 0.5),
color: Colors.grey[300]),
child: Text(
header,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.display1.copyWith(
fontWeight: FontWeight.w700,
fontSize: 14.0,
color: Colors.black87),
),
);
},
tableCellBuilder: (value) {
return Container(
padding: EdgeInsets.symmetric(
horizontal: 4.0, vertical: 2.0),
decoration: BoxDecoration(
border: Border.all(
width: 0.5,
color: Colors.grey.withOpacity(0.5))),
child: Text(
value,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.display1.copyWith(
fontSize: 14.0, color: Colors.grey[900]),
),
);
},
allowRowHighlight: true,
rowHighlightColor: Colors.yellow[500].withOpacity(0.7),
paginationRowCount: 20,
),
SizedBox(
height: 20.0,
),
Text("Simple table which creates table direclty from json")
],
)
: Center(
child: Text(getPrettyJSONString(jsonSample)),
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.grid_on),
onPressed: () {
setState(
() {
toggle = !toggle;
},
);
}),
);
}
String getPrettyJSONString(jsonObject) {
JsonEncoder encoder = new JsonEncoder.withIndent(' ');
String jsonString = encoder.convert(json.decode(jsonObject));
return jsonString;
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SimpleTable(),
);
}
}
I think you should first, convert this json into a real dart class so it can be easier to work with. You could create a class in dart/flutter called "Equipe" and run a map on the json. The [] means that you're dealing with a list of data.
But if you don't want to create a class, you could definitely work with with the json response, mapping over the list. I'm going to try to cook it up for you quickly. NB: Just remember to convert the json too, if it hasn't been done yet.
DataTable(
columnSpacing: 20,
columns: [
DataColumn(
label: Text("Eq 1"),
numeric: false,
tooltip: "",
),
DataColumn(
label: Text("Eq 2"),
numeric: false,
tooltip: "",
),
DataColumn(
label: Text("Type pro"),
numeric: false,
tooltip: "",
),
],
rows: equipeDetails.map((equipeDetail) => DataRow(
cells: [
DataCell(
Text(equipeDetail['equipe1'].toString()),
),
DataCell(
Text(equipeDetail['equipe2'].toString()),
),
DataCell(
Text(equipeDetail['type_prono'].toString()),
),
]),
).toList(),
)
I have done it:
Grille_display() async {
// SERVER LOGIN API URL
var url = 'http://www.axis-medias.fr/game_app/display_grid.php';
// Store all data with Param Name.
var data = {'id_grille': 1};
// Starting Web API Call.
var response = await http.post(url, body: json.encode(data));
// Getting Server response into variable.
var match = json.decode(response.body);
}
I think I need to create 2 class, instead of using equipeDetails and equipeDetail.
I need to display only equipe1 and equipe2 in table and use type prono for display radio button 1N2 or 12.
To populate data Table with json, create 2 methods .
One for populating the column headings.
Second one for populating the rows.
then pass the methods as value to datatable.
DataTable(
columnSpacing: 20,
columns:
dataTableColumnHeaderSetter(
dashBoardItems!
.oSsummary),
rows: dashBoardItems!.oSsummary
.mapIndexed(
(index, details) => DataRow(
cells:
dataTableColumnValueSetter(
dashBoardItems!
.oSsummary),
),
)
.toList()),
Method one.
List<DataColumn> dataTableColumnHeaderSetter(List<OSsummary> summary) {
return List.generate(summary.length, (i) {
return DataColumn(
label: Text(
summary[i].head,
textAlign: TextAlign.center,
),
numeric: true,
tooltip: "",
);
});
}
Method Two.
List<DataCell> dataTableColumnValueSetter(List<OSsummary> summary) {
return List.generate(summary.length, (i) {
return DataCell(
Text(
summary[i].value,
textAlign: TextAlign.center,
),
showEditIcon: false,
placeholder: false,
);
});
}
Do wrap the datatable in future builder and use snapshot.data for accessing the json data.

How to get AlertDialog Callback from method in Flutter?

I have AlertDialog in static method, in that I wants to get callback when user clicks on OK button.
I tried using typedef but can't understand.
Below is My Code:
class DialogUtils{
static void displayDialogOKCallBack(BuildContext context, String title,
String message)
{
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text(title, style: normalPrimaryStyle,),
content: new Text(message),
actions: <Widget>[
new FlatButton(
child: new Text(LocaleUtils.getString(context, "ok"), style: normalPrimaryStyle,),
onPressed: () {
Navigator.of(context).pop();
// HERE I WANTS TO ADD CALLBACK
},
),
],
);
},
);
}
}
You can simply wait for the dialog to be dismissed {returns null} or closed by clicking OK which, in this case, will return true
class DialogUtils {
static Future<bool> displayDialogOKCallBack(
BuildContext context, String title, String message) async {
return await showDialog<bool>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text(title, style: normalPrimaryStyle,),
content: Text(message),
actions: <Widget>[
FlatButton(
child: Text(LocaleUtils.getString(context, "ok"), style: normalPrimaryStyle,),
onPressed: () {
Navigator.of(context).pop(true);
// true here means you clicked ok
},
),
],
);
},
);
}
}
And then when you call displayDialogOKCallBack you should await for the result
Example:
onTap: () async {
var result =
await DialogUtils.displayDialogOKCallBack();
if (result) {
// Ok button is clicked
}
}
Then Callback function for Future work:
DialogUtils.displayDialogOKCallBack().then((value) {
if (value) {
// Do stuff here when ok button is pressed and dialog is dismissed.
}
});
This thread is a bit old, but I found a solution that wasn't touched upon, so I thought I'd add it here.
I had a form in my AlertDialog, and I needed to keep the dialog open if there were any errors. This solution worked for me.
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
Future _showEditDialog(BuildContext context) {
return showDialog(
context: context,
builder: (context) {
return WillPopScope(
onWillPop: () async {
return formKey.currentState!.validate();
},
child: AlertDialog(
title: const Text("Awesome AlertDialog"),
content: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Form(
key: formKey,
child: Column(
children: [
TextFormField(
validator: (value) {
if (value!.isEmpty) return "Please Fill Out This Field";
return null;
},
),
],
),
),
),
actions: <Widget>[
MaterialButton(
child: const Text("Cancel"),
onPressed: () {
Navigator.pop(context);
},
),
],
),
);
},
);
}
The important part is the WillPopScope that I wrapped the AlertDialog. I think this absorbs all the Navigator.pop() calls and passes them through the onWillPop parameter. This parameter is passed an async function which returns a Future. I just returned the validation check boolean, but in the real world there would also be a http request here too.
Remember to add a way for the user to cancel the form without triggering the form validation. I just added a cancel button that runs Navigator.pop().
Hope this helps, let me know if anyone has any questions.