Flutter How to use DropDowns selected item on http.post - flutter

I have a drop down button with a list of items in it that are fetched from the api, i need to send to the server the id of the selected item. So right when the user chooses the item and presses the Start Working button i need to send the chosen items id to the server, the problem that im having is working out with sending the chosen items id.
Future<void> postLocationId(String id) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String? authorization = prefs.getString('authorization');
var url = 'some url';
try {
final response = await http.post(
Uri.parse(url),
headers: <String, String>{
'authorization': authorization ?? basicAuth.toString(),
"Content-Type": "application/json"
},
body: jsonEncode(id)
);
print(response.statusCode);
print(id);
} catch (er) {}
}
String? chooseLocation;
late Future<Response> futureData;
late Future<Response> futureDataForAccount;
bool _flag = true;
List<WorkingLocationData>? workingData;
List<AccountData>? accountData;
Scaffold(
body: FutureBuilder<List<Response>>(
future: Future.wait([futureData, futureDataForAccount]),
builder: (context, snapshot) {
if (snapshot.hasData) {
List<WorkingLocationData> data1 =
parsedData(snapshot.data![0].body);
workingData = data1;
AccountData data3 =
AccountData.fromJson(json.decode(snapshot.data![1].body));
child: DropdownButton<String>(
value: chooseLocation,
hint: const Text('Select a location'),
isExpanded: true,
items: workingData!.map((some) {
return DropdownMenuItem(
child: Text(some.name + ' (${some.location})'),
value: some.id,
);
}).toList(),
onChanged: (String? displayedValue) {
setState(
() {
chooseLocation = displayedValue!;
},
);
},
),
),
SizedBox(height: height * 0.150),
Column(
children: [
ElevatedButton(
onPressed: () async {
final WorkingLocationData locatonData = workingData!.firstWhere((some) => some.location == chooseLocation);
await postLocationId(locatonData.id);
print(locatonData.id);
setState(() {
_flag = !_flag;
});
},
child: Text(_flag ? 'Start Work' : 'Stop Work'),
style: ElevatedButton.styleFrom(
primary: _flag ? Colors.teal : Colors.red,
),
),
],

You need to add the parameter you want: postLocationId(String id).
Without changing the structure too much you can search through workingData for the item with the matching location and pass it on press like:
ElevatedButton(
onPressed: () async {
final WorkingLocationData locatonData = workingData!.firstWhere((some) => some.location == chooseLocation);
postLocationId(locatonData.id);
setState(() {
_flag = !_flag;
});
},
child: Text(_flag ? 'Start Work' : 'Stop Work'),
style: ElevatedButton.styleFrom(
primary: _flag ? Colors.teal : Colors.red,
),
),
If you're interested in a larger structural change I use https://pub.dev/packages/flutter_typeahead for this kind of thing

Related

Obx is not refreshed after login, if the page is refreshed its working fine

i'm developing an App with two pages.i use getx and my problem is obx is not refreshed after login eventhough i called the function on initstate and declared the variable as .obs,search is not working and everything is get freezed.When i refresh the page everything is working fine.
This is my UI
`class LandingPage extends StatefulWidget {
const LandingPage({super.key});
#override
State<LandingPage> createState() => _LandingPageState();
}
class _LandingPageState extends State<LandingPage> {
TextEditingController dateInput = TextEditingController();
final scaffoldKey = GlobalKey<ScaffoldState>();
late Future futureTasks;
String? name;
String? email;
String? image;
var isselected = false.obs;
#override
void initState() {
controller.fetchTodo();
super.initState();
}
final controller = Get.put(ToDoController());
final usercontroller = Get.put(UserController());
#override
Widget build(BuildContext context) {
return Obx(
(() {
return Column(
children: controller.todo.value.where((element) {
if (controller.search.value != '') {
return element.title!
.toString()
.toLowerCase()
.contains(controller.search.value)
}
return true;
}).map((todo) {
return Stack(
children: [
Card(
child: ExpansionTile(
initiallyExpanded: false,
subtitle: Padding(
padding: const EdgeInsets.fromLTRB(7, 3, 0, 6),
child: Wrap(
spacing: 8,
runSpacing: 8,
children: todo.labels!.map((lable) {
return ChipMv(lable: lable);
}).toList()),
),
title: Align(
alignment: Alignment.topLeft,
child: TextButton(
child: Text(
GetUtils.capitalizeFirst(todo.title ?? "")
.toString(),
style:
Theme.of(context).primaryTextTheme.headline5),
),
),
children: [
Align(
alignment: Alignment.topLeft,
child: Container(
child: ListTile(
title: Form(
child: TextFormField(
controller: controller.task,
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(Icons.add),
onPressed: () {
controller.taskCreate(todo.id);
}),
hintText: " Add Task",
),
),
),
),
),
),
Column(
children: todo.tasks!
.map((task) => Align(
alignment: Alignment.topLeft,
child: Container(
child: CheckboxListTile(
checkboxShape: CircleBorder(),
onChanged: (value) {
task.complete = value;
controller.todoStatus(
todo.id, task.tid, task.complete);
},
value: task.complete,
controlAffinity:
ListTileControlAffinity.trailing,
secondary: IconButton(
icon: Icon(Icons.delete_outlined),
color:
Colors.redAccent.withOpacity(0.6),
onPressed: () {
Get.defaultDialog(
content: Text(
"Are you want to remove task?"),
actions: <Widget>[
TextButton(
onPressed: () {
Get.back();
},
child: const Text('Cancel'),
),
TextButton(
onPressed: () {
controller.taskDelete(
todo.id, task.tid);
setState(() {});
},
child: const Text('OK'),
),
],
);
},
),
title: Text(
task.task ?? "",))
.toList(),
),
], ],
);
}
},
),
),
),
],
);
}).toList())
]);
}),
);
}
}
This my controller class
`Future<List<Todo>> fetchTodo() async {
isloading.value = true;
Uri url = Uri.parse('$dev/todo/todo/list');
SharedPreferences preferences = await SharedPreferences.getInstance();
var token = preferences.getString("token");
print(token);
// Starting Web API Call.
var response = await http.post(
url,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer $token',
},
);.
if (response.statusCode == 200) {
final datas = json.decode(response.body).cast<Map<String, dynamic>>();
tasks = datas.map<Todo>((json) {
return Todo.fromJson(json);
}).toList();
todo.value = datas.map<Todo>((json) {
return Todo.fromJson(json);
}).toList();
isloading.value = false;
return todo;
} else {
isloading.value = false;
return todo;
}
}
`
instead of returning todo like that,
try to do like this:
in controller declare a RxList:
RxList<Todo> todoList = <Todo>[].obs;
and change the fetchTodo like this:
Future<void>fetchTodo() async {
//some codes to receive todoList
todoList.value = something; // todoList you received from above
todoList.refresh();
}
import 'dart:html' as html;
Future Login() {
Uri url = Uri.parse('url here');
// Starting Web API Call.
var response = await http.post(url,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: body);
if (response.statusCode == 200) {
html.window.location.reload();
} else {
Get.snackbar("Failed!", "Username and Password not found");
}
it reloads the page after login and everything works fine.

Flutter-during navigation want text variable is returning null(want to prioritize the function in navigation during elevated Button)

I am sending an image to API and I want to show Snackbar to display if image is uploaded or not.
I have defined text variable in class. And then from API response I am changing that variable but during Elevated button navigation value of text is changed but it is showing that is previously assigned.
This my f
Future CreateAuditAPI(String userId, String warehouseId, String base64IMG, String description) async{
final Uri uri = Uri.parse("https://firebase.google.com/" );/*sample url for getting response I know it wil not work*/
CreateAudit obj = CreateAudit(
userID: userId,
warehouseID: warehouseId,
description: [description],
imagedata: [base64IMG]
);
var d = jsonEncode(obj);
print("printing data before passing");
print(d);
try {
print("printing in try");
final http.Response response = await client.post(uri,
headers: headers, body: d);
Map<String, dynamic> jsonResponse = jsonDecode(response.body);
if (jsonResponse["status"] == 200) {
text = jsonResponse["message"];
return jsonResponse["data"];
} else {
text = "Something Went Wrong";
throw Exception(jsonResponse["msg"]);
}
} catch(e) {
print(e);
}
}
and the displaying of Snackbar is going here
class DisplayScreen extends StatefulWidget {
/*DisplayScreen({super.key, required this.imagePath});*/
String imagePath;
String warehouseid ;
DisplayScreen(this.imagePath, this.warehouseid);
#override
State<DisplayScreen> createState() => _DisplayScreenState();
}
class _DisplayScreenState extends State<DisplayScreen> {
String? dropdownBuldingtype = '';
String? _imagData;
String? userID;
String? text='Uploaded Successfully';
Future<String> getExifFromFile() async {
if (File(widget.imagePath) == null) {
return "";
}
final fileBytes = File(widget.imagePath)!.readAsBytesSync();
final data = await readExifFromBytes(fileBytes);
if (data.isEmpty) {
print("No EXIF information found");
return "";
}
final datetime = data['EXIF DateTimeOriginal']?.toString();
if (datetime == null) {
print("datetime information not found");
return "";
}
String? datetime1;
datetime1 = datetime;
print(widget.imagePath);
File imagefile = File(widget.imagePath); //convert Path to File
Uint8List imagebytes = await imagefile.readAsBytes(); //convert to bytes
_imagData = base64.encode(imagebytes); //convert bytes to base64 string
return datetime1;
}
Future CreateAuditAPI(String userId, String warehouseId, String base64IMG, String description) async{
final Uri uri = Uri.parse("https://firebase.google.com/" );
print('insidewarehouse');
print(uri);
CreateAudit obj = CreateAudit(
userID: userId,
warehouseID: warehouseId,
description: [description],
imagedata: [base64IMG]
);
var d = jsonEncode(obj);
print("printing data before passing");
print(d);
try {
print("printing in try");
final http.Response response = await client.post(uri,
headers: headers, body: d);
Map<String, dynamic> jsonResponse = jsonDecode(response.body);
if (jsonResponse["status"] == 200) {
text = jsonResponse["message"];
return jsonResponse["data"];
} else {
text = 'Something Went Wrong';
throw Exception(jsonResponse["msg"]);
}
} catch(e) {
print(e);
}
}
void getuserid() async{
SharedPreferences _prefs = await SharedPreferences.getInstance();
userID = _prefs.getString("userid");
}
TextEditingController description = TextEditingController();
final client = http.Client();
final headers ={
'Content-type': 'application/json'
};
/*var data;*/
#override
void initState() {
getuserid();
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
print("attal======>"+widget.imagePath);
/*data = ModalRoute.of(context)!.settings.arguments;
// dropdownBuldingtype = data["buidlingtype"];
print(data);*/
getExifFromFile();
getuserid();
print("atal");
print(widget.imagePath);
/*String? warehouseID= data["warehouseid"].toString();
print(warehouseID);*/
final size = MediaQuery
.of(context)
.size;
final String _description = description.text;
String? warehouseID = widget.warehouseid;
print('warehiii');
print(warehouseID);
print('useriiiiiii');
print(userID);
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
leading: IconButton(icon: const Icon(Icons.close, color: Colors.red, size: 50,), padding: EdgeInsets.all(4.0), onPressed: () {Navigator.pop(context); },),
actions: [IconButton(icon: const Icon(Icons.check, color: Colors.green, size: 50,), padding: EdgeInsets.only(right: 4.0),onPressed: () {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
actions: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(onPressed: (){
Navigator.of(ctx).pop();
}, icon: Icon(Icons.close, color: Colors.red,) )
],
),
Padding(padding: EdgeInsets.symmetric(horizontal: size.width*0.07),
child: Text('Description : ', style: TextStyle(fontWeight: FontWeight.bold),),
),
SizedBox(height: 20,),
Padding(
padding: EdgeInsets.symmetric(horizontal: size.width*0.07),
child: TextFormField(
controller: description,
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.black, width: 2)),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey, width: 1 ),),
),
),
),
SizedBox(height: size.height*0.05,),
Padding(
padding: EdgeInsets.symmetric(horizontal: size.width*0.07),
child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ElevatedButton(onPressed: (){}, child: Text('More Image'),style: ElevatedButton.styleFrom(
primary: Colors.orange.withOpacity(0.8),
),),
ElevatedButton(onPressed: (){CreateAuditAPI(userID!,warehouseID,_imagData!,description.text);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("$text"),action: SnackBarAction(label: 'OK',onPressed: (){
Navigator.pop(context);
},),));
Navigator.pop(context);
},
child: Text('Upload'), style: ElevatedButton.styleFrom(
primary: Colors.orange.withOpacity(0.8),
),)
],
),
)
],
),
],
),
);},)],
),
backgroundColor: Colors.black,
/*appBar: AppBar(title: const Text('Display the Picture')),*/
// The image is stored as a file on the device. Use the `Image.file`
// constructor with the given path to display the image.
body: SizedBox.expand(child: Image.file(File(widget.imagePath),
)),
);
}
}
this is the issue.......
ElevatedButton(onPressed: (){CreateAuditAPI(userID!,warehouseID,_imagData!,description.text);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("$text"),action: SnackBarAction(label: 'OK',onPressed: (){
Navigator.pop(context);
},),));
Navigator.pop(context);
},
child: Text('Upload'), style: ElevatedButton.styleFrom(
primary: Colors.orange.withOpacity(0.8),
),)
it is calling API on the console it is uploading but in Snackbar it is not assigning the new value to text variable. Elevated Button is calling function of create Audit but it doing the Create Audit and Showing snackbar at the same time and not give the updated value of text to the Snackbar.
I have tried removing sncakbar from the elevated button and putting Snackbar in CreateAuditAPI function but it is not calling the snackbar.
i guess the problem that there is no waiting for the request as its handled as sync
you should await for the api request
ElevatedButton(onPressed: () async {
await CreateAuditAPI(userID!,warehouseID,_imagData!,description.text);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content:Text("$text"),action: SnackBarAction(label: 'OK',onPressed: (){ Navigator.pop(context);
},),));
Navigator.pop(context);
},

Flutter Dropdown value not updating and UI not updating when submitting

I am working on a flutter project to display a Scrumboard, this is my first time working with flutter. I have a TextButton that opens a dialog when onpressed. The dialog is a form where you can edit details about a Scrumtask. I have discovered 2 issues. 1. issue is when i use the dropdownmenu and select a value. The value doenst get updated. 2. Lets say i edit a Scrumtask and set the state from 'Todo' to 'In Progress' from the dropdownmenu and submit, the UI doesn't move that Task object to the 'In Progress' column.
I hope the code I have provided is enough otherwise let me know.
Scrumboardscreen.dart
TextButton(
child: Text('Change'),
onPressed: () {
showDialog(
context: context,
builder: ((context) {
return AlertDialog(
title: Text('Task Informations'),
content: Form(
key: _formKey,
child: Column(
children: [
Text('Task Name'),
TextFormField(
controller: textscontrollers[0],
decoration: InputDecoration(
hintText: data[listIndex]
.items[itemIndex]
.taskName,
),
validator: (text) {
if (text == null || text.isEmpty) {
return 'Task Name cant be empty';
}
return null;
},
),
Text('Task Description'),
TextFormField(
controller: textscontrollers[1],
decoration: InputDecoration(
hintText: data[listIndex]
.items[itemIndex]
.taskDescription,
),
validator: (text) {
if (text == null || text.isEmpty) {
return 'Task Description cant be empty';
}
return null;
},
),
Text('Story Points'),
TextFormField(
controller: textscontrollers[2],
decoration: InputDecoration(
hintText: data[listIndex]
.items[itemIndex]
.storyPoints
.toString(),
),
validator: (text) {
if (text == null || text.isEmpty) {
return 'Story Points cant be empty';
}
return null;
},
),
Text('Task State'),
DropdownButton<String>(
value: data[listIndex]
.items[itemIndex]
.taskState,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(
color: Colors.blue,
),
underline: Container(
height: 2,
color: Colors.blue,
),
onChanged: (String? value) {
setState(() {
data[listIndex]
.items[itemIndex]
.taskState = value!;
});
},
items: states
.map<DropdownMenuItem<String>>(
(String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!
.validate()) {
_UpdateTask(data[listIndex]
.items[itemIndex]);
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(
content:
Text('Updated Task')));
Navigator.of(context).pop();
}
},
child: Text('Submit Changes'),
)
],
),
),
);
}));
},
),
This method is being in the Futurebuilder and shows data on the UI
Future<List<BoardPostColumn>> GetData() async {
if (data.isEmpty) {
data = await manager.GetData();
}
return data;
}
The update method
void _UpdateTask(BoardPost task) async {
task.taskName = textscontrollers[0].text;
task.taskDescription = textscontrollers[1].text;
task.storyPoints = int.parse(textscontrollers[2].text);
BoardPost result = await manager.UpdateTask(task);
setState(() {
//My understanding that this would update the UI
task = result;
textscontrollers[0].clear();
textscontrollers[1].clear();
textscontrollers[2].clear();
});
}
Manager class
Future<BoardPost> UpdateTask(BoardPost task) async {
return handler.UpdateTask(task);
}
ApiHandler.dart
Future<BoardPost> UpdateTask(BoardPost task) async {
Response response = await post(
Uri.parse('https://localhost:7252/api/ScrumTask/UpdateScrumTask'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, dynamic>{
'id': task.id,
'taskName': task.taskName,
'taskDescription': task.taskDescription,
'storyPoints': task.storyPoints,
'taskState': task.taskState
}));
if (response.statusCode == 200) {
Map<String, dynamic> ScrumMap = jsonDecode(response.body);
return BoardPost.fromJson(ScrumMap);
} else {
throw Exception('Failed to Update');
}
}
class BoardPost {
int? id;
String? taskName;
String? taskDescription;
int? storyPoints;
String? taskState;
BoardPost(
{this.id,
this.taskName,
this.taskDescription,
this.storyPoints,
this.taskState});
BoardPost.fromJson(Map<String, dynamic> json) {
id = json['id'];
taskName = json['taskName'];
taskDescription = json['taskDescription'];
storyPoints = json['storyPoints'];
taskState = json['taskState'];
}
This class here is the one that will be displaying all the data
class BoardPostColumn {
String title;
List<BoardPost> items;
BoardPostColumn({
required this.title,
required this.items,
});
}
Manager class that returns the data provided from api
Future<List<BoardPostColumn>> GetData() async {
Response responseBody = await handler.GetData();
List<BoardPostColumn> data = [];
List<BoardPost> tasks = (json.decode(responseBody.body) as List)
.map((data) => BoardPost.fromJson(data))
.toList();
data.add(BoardPostColumn(
title: 'To do',
items:
tasks.where((e) => e.taskState?.toLowerCase() == 'todo').toList()));
data.add(BoardPostColumn(
title: 'In Progress',
items: tasks
.where((e) => e.taskState?.toLowerCase() == 'in progress')
.toList()));
data.add(BoardPostColumn(
title: 'Done',
items:
tasks.where((e) => e.taskState?.toLowerCase() == 'done').toList()));
return data;
}
Try to use StatefulBuilder inside showDialog to update the dialog ui.
showDialog(
context: context,
builder: (context) {
return StatefulBuilder(builder: (context, setStateSB) => AlertDialog(...),)
},
);
Use this setStateSB as setState to update the dialog ui, You may need to pass this setStateSB on the function or call it setStateSB((){}) at the end of the function call.

Can I save an id from API using shared preferences where I can retrieve it's contents e.g. name, age, location, ect

In the preferences I would like to save the user id so that in next page I could use its id to create a profile page for the user. as of now I can only pass the name of the user. I want to somehow get the id so that I can pull another json file for profile page
void login() async {
if (userController.text.isNotEmpty &&
passController.text.isNotEmpty) {
var postUrl = "http://serverUrl";
var auth = "auth.json";
var login = postUrl + auth;
var data = jsonEncode(
{"username": userController.text, "password":
passController.text});
http.Response res = await http.post(Uri.parse(login),
headers: {"Content-Type": "application/json"}, body: data);
if (res.statusCode == 200) {
final resData = jsonDecode(res.body);
String message = (resData['response']['message']);
String fName = (resData['response']['member_info']['fname']);
String lName = (resData['response']['member_info']['lname']);
String fullName = fName + " " + lName;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(message),
));
pageRoute(fullName);
} else if (res.statusCode == 400) {
final resData = jsonDecode(res.body);
String message = (resData['response']['message']);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(message),
));
}
} else {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text("No username or password"),
));
}
}
void pageRoute(String fullName) async {
SharedPreferences pref = await SharedPreferences.getInstance();
await pref.setString("data", fullName);
Navigator.of(context).pushAndRemoveUntil(
CupertinoPageRoute(builder: (context) => const ProfilePage()),
(route) => false
);
}
}
//Here is my code for the Profile page where I will retrieve the stored data in the shared preferences
class _ProfileInfoState extends State<ProfileInfo> {
String fullName = "";
late int memberId;
#override
void initState() {
super.initState();
getData();
}
void getData() async {
//Fetching of Data
SharedPreferences pref = await SharedPreferences.getInstance();
setState(() {
fullName = pref.getString("data")!;
memberId = pref.getInt("data")!;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: NavigationDrawerWidget(),
appBar: AppBar (
title: SizedBox(
height: 45,
width: 180,
child: Image.asset('images'),
),
elevation: 10.0,
flexibleSpace: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Colors.deepOrangeAccent, Colors.green],
begin: Alignment.bottomRight,
end: Alignment.topLeft
),
),
),
actions: [
IconButton(
icon: const Icon(Icons.shopping_cart_rounded),
onPressed: () {
// print('cart');
},
),
IconButton(
icon: const Icon(Icons.home),
onPressed: () {
// print('home');
},
),
],
),
body: SafeArea(
child: Center(
child: Column(
children: [
const Padding(
padding: EdgeInsets.all(50.0),
child: Text(
"Welcome User",
style: TextStyle(fontSize: 20),
),
),
const SizedBox(
height: 150,
),
Text("Name: $fullName"),
Text("Name: $memberId"),
const SizedBox(
height: 35,
),
],
),
),
),
);
}
}
yes you can save your id which you retrieve from the api to shared preference
but Before saving the id to shared preference you need to check if id is not-null then it will save other wise not save to shared preference.. if you share your code then i will solve it for you if you want
As you are passing fullName in pageRoute method, you can also pass the id of user (If you are getting in response).
For example:
int id = (resData['response']['member_info']['id']); //if key is 'id'
pageRoute(id, fullName);
And you function will be like:
void pageRoute(int id, String fullName) async {
SharedPreferences pref = await SharedPreferences.getInstance();
await pref.setString("data", fullName);
await pref.setInt("id", id);
Navigator.of(context).pushAndRemoveUntil(
CupertinoPageRoute(builder: (context) => const ProfilePage()),
(route) => false
);
}
}
Then you can use it on ProfilePage as you are using fullName.
Do let me know if you need any other help. Thanks!

Query in button error on the first click flutter

I have problem in button to search user by phone number. When I press button for the first time, query can't retrieve the data, like this : Debug Console 1. But if I press button again for the second time or more, query can retrieve the data, like this : Debug Console 2.
This is my button code :
Widget tmblKonfirm() {
return Center(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
),
child: FlatButton(
onPressed: () async{
await pr.show();
print('NoHP : ' + nohp);
final dataUser = FirebaseDatabase.instance
.reference()
.child("users")
.orderByChild("pengguna_nomor")
.equalTo(nohp);
print('Data User : ' + dataUser.toString());
dataUser.once().then((DataSnapshot snapshot) {
Map<dynamic, dynamic> data = snapshot.value;
setState(() {
testUser = snapshot.value.toString();
});
data.forEach((key, values) {
lists.add(values);
});
});
print('User 1 : ' + lists.toString());
pr.hide();
if (_formKeyKonfirm.currentState.validate()) {
print('User 2 : ' + testUser.toString());
if (testUser != 'null'){
// setState(() {
sttsUser = true;
// });
// showWidgetTopup();
}
else {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text(
'Nomor HP tidak terdaftar'),
actions: <Widget>[
FlatButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('OK'),
)
],
);
},
);
}
}
},
child: Text('Konfirmasi',
style: TextStyle(color: Colors.black, fontSize: 25)),
color: Colors.lightBlue,
),
));
}
dataUser is a Query so you always have to fetch the data snapshot (once() or onValue)
Instead of dataUser.once().then use await dataUser.once(), otherwise the snapshot callback can be actually called after the onPressed function finishes