Pass arguments from Modal Route to a post http request in Flutter - flutter

I'm passing arguments with pushNamed to a screen and I can access it inside my ListView but then I want to send some of the arguments with an ElevatedButton to my post request but I can't access it. I've tried many ways to do this can someone tell me what I'm doing wrong? Thanks in advance!
Where I use pushNamed
child: ElevatedButton(
style: ElevatedButton.styleFrom(
disabledBackgroundColor: Colors.grey),
onPressed: (() async {
Navigator.of(context).pushNamed(
SelectedAthletes.routeName,
arguments: selectedAthlete.toList());
})
The screen I'm passing the argument
class SelectedAthletes extends StatefulWidget {
const SelectedAthletes({Key? key}) : super(key: key);
static const routeName = '/selectedAthletes';
#override
State<SelectedAthletes> createState() => _SelectedAthletesState();
}
class _SelectedAthletesState extends State<SelectedAthletes> {
#override
Widget build(BuildContext context) {
final args = ModalRoute.of(context)!.settings.arguments as List<Athlete>;
return Scaffold(
backgroundColor: const Color(0Xfff7f7f5),
body: Stack(
children: [
SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ListView.builder(
shrinkWrap: true,
cacheExtent: 34,
primary: true,
physics: const ClampingScrollPhysics(),
padding: const EdgeInsets.only(
top: 10,
bottom: 56,
),
itemCount: args.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: const Icon(Icons.history_outlined,
color: Colors.black, size: 25),
title: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'ID: ${args[index].id}',
style: const TextStyle(
color: Colors.blue, fontSize: 14),
),
const SizedBox(
width: 5,
),
Row(
children: [
Flexible(
child: Text(
'${args[index].lastName} ${args[index].firstName}',
style: const TextStyle(
color: Colors.black,
fontFamily: 'Cera',
fontWeight: FontWeight.bold,
fontSize: 18),
),
),
],
),
const SizedBox(
height: 5,
),
Row(
children: [
Text(
'(${args[index].fatherName})',
style: const TextStyle(
color: Colors.black,
fontFamily: 'Cera',
fontSize: 14),
),
const SizedBox(
width: 20,
),
Text(
'Π: ${args[index].currentMonthPresences}',
style: const TextStyle(
color: Colors.black,
fontFamily: 'Cera',
fontSize: 14),
),
const SizedBox(
width: 50,
),
],
),
],
));
},
)
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
width: double.infinity,
height: 60,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
disabledBackgroundColor: Colors.grey),
onPressed: () async {
await ApiService.insertPresences(args[index].id, args[index].firstName, args[index].lastName);
},
child: const Center(
child: Text(
'SEND',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 18),
),
),
),
),
),
],
));
}
My post request
static Future<Athlete> insertPresences(
int athleteId, int departmentId, int teamId) async {
try {
final response = await http.post(
Uri.parse(
'http://164.92.170.94:8080/nox/api/nox/api/insert-presences'),
headers: {
'Authorization': 'Basic a2F4cmlzOjEyMzQ1',
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: jsonEncode(<String, int>{
"athleteId": athleteId,
"departmentId": departmentId,
"teamId": teamId,
}));
print('Response status: ${response.statusCode}');
print('Response body: ${response.body}');
if (response.statusCode == 201) {
return Athlete.fromJson(jsonDecode(response.body));
}
} catch (e) {
logger.e(e.toString());
}
return insertPresences(athleteId, departmentId, teamId);
}
Error in my ElevatedButton in SelectedAthletes screen
Undefined name 'index'.
Try correcting the name to one that is defined, or defining the name.

You passed a List to your second screen and you need to specify which item you want to pass to your api.
If you want pass the first item, simply use 0 instead of index like this:
onPressed: () async {
await ApiService.insertPresences(args[0].id, args[0].firstName, args[0].lastName);
},
And if you want to show a button for all items, you need to move the ElevatedButton widget to your ListView.builder widget like this:
ListView.builder(
...,
itemBuilder: (BuildContext context, int index) {
//You can use index here
return ListTile(
...,
title: Column(
children: [
...,//some other widgets
ElevatedButton(
...,
onPressed: () async {
await ApiService.insertPresences(args[index].id, args[index].firstName, args[index].lastName);
},
]
);
}
)

Related

How to merge new field value to an existing firestore document with flutter?

I am trying to assign a delivery agent to the order of products with a dropdown containing a list of delivery agents. I am trying to get documentId and merging new field value to the documentId which already exists. But as a result, I a getting a duplicate document with the same documentId containing filed values which I want to merge. kindly help me to understand what I am doing wrong.
full code order_view.dart
import 'package:flutter/material.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart';
import '../../services/firebase_database.dart';
import '../widgets/snack_bar.dart';
import 'client_address.dart';
import 'dashboard.dart';
import 'package:url_launcher/url_launcher.dart';
class OrderView extends StatefulWidget {
final Map<String, dynamic> orderData;
final List<String> deliveryAgent;
const OrderView(
{Key? key, required this.orderData, required this.deliveryAgent})
: super(key: key);
#override
State<OrderView> createState() => _OrderViewState();
}
class _OrderViewState extends State<OrderView> {
final FirebaseDatabase _database = FirebaseDatabase();
int index = 0;
num totalAmount = 0;
Map<String, dynamic> clientData = {};
getcountTotalAmount() async {
for (var item in widget.orderData["orders"]) {
totalAmount = totalAmount + (item["productPrice"] * item["amount"]);
}
clientData = (await _database.getClientData(widget.orderData["userId"]))!;
setState(() {});
}
#override
void initState() {
getcountTotalAmount();
super.initState();
}
#override
Widget build(BuildContext context) {
bool _isloading = true;
return Scaffold(
backgroundColor: Colors.grey[200],
appBar: AppBar(
elevation: 4,
title: const Text("Open Order"),
actions: [
TextButton(
onPressed: () async {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: const Text(
"Are you sure you want to cancel this order?",
textAlign: TextAlign.center,
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text(
"No",
style:
TextStyle(color: Colors.green, fontSize: 16),
)),
TextButton(
onPressed: () async {
// Navigator.pop(context);
showDialog(
context: context,
builder: (context) {
return LoadingAnimationWidget.inkDrop(
color: Colors.orange,
size: 50,
);
});
await _database.removeOrder(
createTime: widget.orderData["createAt"],
);
Navigator.of(context).pop();
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) =>
const AdminDashboard()),
ModalRoute.withName(''),
);
ScaffoldMessenger.of(context).showSnackBar(
snackBar(
message: "Your order is removed",
color: Colors.deepOrange),
);
},
child: const Text(
"Yes",
style: TextStyle(color: Colors.red, fontSize: 16),
)),
],
);
});
},
child: const Text(
"Cancel Order",
style: TextStyle(
color: Colors.red,
fontWeight: FontWeight.w500,
fontSize: 15,
),
),
),
],
),
body: SizedBox(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: ListView(
physics: const BouncingScrollPhysics(),
children: [
Container(
color: Colors.white,
child: ListView.separated(
padding: const EdgeInsets.symmetric(vertical: 8),
shrinkWrap: true,
itemCount: widget.orderData["orders"].length,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) {
return ListTile(
leading: Image.network(
widget.orderData["orders"][index]["productImage"],
),
title: Text(
widget.orderData["orders"][index]["productTitle"],
),
subtitle: SizedBox(
width: MediaQuery.of(context).size.width,
child: Row(
children: [
Text(
"₹ ${widget.orderData["orders"][index]["productPrice"]}",
style: const TextStyle(
color: Colors.green, fontSize: 12),
),
const Text(" - "),
Text(
widget.orderData["orders"][index]["productUnit"],
style: const TextStyle(fontSize: 12),
),
const Text(" x "),
Text(widget.orderData["orders"][index]["amount"]
.toString()),
const SizedBox(width: 5),
Text(
"Total ₹ ${widget.orderData["orders"][index]["productPrice"] * widget.orderData["orders"][index]["amount"]}",
style: const TextStyle(
color: Colors.green,
fontWeight: FontWeight.w600,
fontSize: 12,
),
),
],
),
),
);
},
separatorBuilder: (BuildContext context, int index) {
return const Divider();
},
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('Delivery Slot'),
Text(
'${widget.orderData["deliverySlot"]}',
style: const TextStyle(
fontWeight: FontWeight.w500, fontSize: 16),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
"Delivery charge: ₹${widget.orderData["taxes"]}",
),
Text(
"Total Price: ₹${totalAmount + widget.orderData["taxes"]}",
style: const TextStyle(
fontWeight: FontWeight.w500, fontSize: 16),
),
],
)
],
),
),
const SizedBox(height: 16),
Container(
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
decoration: const BoxDecoration(
color: Colors.white,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Ordered on: ${widget.orderData["createAt"]}',
style: const TextStyle(
fontWeight: FontWeight.w600,
fontSize: 14,
),
),
Text(
'Delivery at ${widget.orderData["addressType"]}',
),
const SizedBox(
height: 16,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.6,
child: Text(
'Address: ${widget.orderData["address"]}',
),
),
ElevatedButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => ClientAddress(
lat: widget.orderData["latitude"],
lag: widget.orderData["longitude"],
)));
},
child: const Text('Open location'))
],
),
],
),
),
const SizedBox(
height: 16,
),
Container(
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Client Details",
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 17,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
child: Text(
clientData["username"] ?? "",
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 15,
),
),
),
SizedBox(
child: Text(
clientData["contact"] ?? "",
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 15,
),
),
),
ElevatedButton.icon(
onPressed: () async {
String telephoneNumber = clientData["contact"];
Uri telephoneUrl = Uri.parse("tel:$telephoneNumber");
if (await canLaunchUrl(telephoneUrl)) {
await launchUrl(telephoneUrl);
}
},
icon: const Icon(
Icons.call,
),
label: const Text('Call'),
)
],
),
],
),
),
const SizedBox(
height: 16,
),
Container(
width: MediaQuery.of(context).size.width,
color: Colors.white,
padding: const EdgeInsets.only(bottom: 8),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text(
"Delivery Agent",
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
),
),
DropdownButton(
items: widget.deliveryAgent
.map(
(e) => DropdownMenuItem(
value: e,
child: Text(e),
),
)
.toList(),
onChanged: (val) {
setState(() {
index =
widget.deliveryAgent.indexOf(val.toString());
});
},
isExpanded: false,
hint: Text(
widget.deliveryAgent[index],
style: const TextStyle(
fontWeight: FontWeight.w600,
fontSize: 15,
),
),
),
],
),
ElevatedButton(
onPressed: () async {
bool results;
results = await _database.updateDeliveryAgent(
orderId: widget.orderData["orderId"],
deliveryAgent: widget.deliveryAgent[index].toString(),
);
if (results) {
setState(() {
_isloading = true;
});
ScaffoldMessenger.of(context).showSnackBar(
snackBar(
message: "Delivery agent assigned",
color: Colors.green,
),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
snackBar(
message: "Error",
color: Colors.red,
),
);
}
setState(() {
_isloading = true;
});
},
child: const Text('Assign Agent')),
],
)),
],
),
),
);
}
}
firebase_database.dart
CollectionReference<Map<String, dynamic>> testorders =
FirebaseFirestore.instance.collection('testorders');
Future<bool> updateDeliveryAgent(
{required String orderId, required String deliveryAgent}) async {
try {
testorders.doc(orderId).set({
"deliveryAgent": {
"agentName": deliveryAgent,
"agentContact": '',
},
}, SetOptions(merge: true));
return true;
} catch (e) {
if (kDebugMode) {
print("error while assigning delivery agent: $e");
}
}
return false;
}
order.dart
Container(
width: MediaQuery.of(context).size.width,
color: Colors.white,
padding: const EdgeInsets.only(bottom: 8),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text(
"Delivery Agent",
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
),
),
DropdownButton(
items: widget.deliveryAgent
.map(
(e) => DropdownMenuItem(
value: e,
child: Text(e),
),
)
.toList(),
onChanged: (val) {
setState(() {
index =
widget.deliveryAgent.indexOf(val.toString());
});
},
isExpanded: false,
hint: Text(
widget.deliveryAgent[index],
style: const TextStyle(
fontWeight: FontWeight.w600,
fontSize: 15,
),
),
),
],
),
ElevatedButton(
onPressed: () async {
bool results;
results = await _database.updateDeliveryAgent(
orderId: widget.orderData["orderId"],
deliveryAgent: widget.deliveryAgent[index].toString(),
);
if (results) {
setState(() {
_isloading = true;
});
ScaffoldMessenger.of(context).showSnackBar(
snackBar(
message: "Delivery agent assigned",
color: Colors.green,
),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
snackBar(
message: "Error",
color: Colors.red,
),
);
}
setState(() {
_isloading = true;
});
},
child: const Text('Assign Agent')),
],
)),
You cannot update a document ID once it's been defined.
See the following answer on alternative steps you can take: https://stackoverflow.com/a/52117929/9063088
There is no way you can have duplicate document IDs inside the same collection. The screenshot shows two documents sharing the same ID but for sure one of them contains one or more white spaces at the end. So there are two situations, the orderId is correct and when you call set() it adds the document with a document ID that doesn't contains white spaces, while in the database there is already one present that contains white spaces, or vice versa. When it comes to document IDs, always call .trim() so it can remove the white spaces from the beginning and from the end.
I fixed this, the main reason was firstly when I created the document with .add() where firebase auto generate the document ID, the and later while merging data in the same document ID it was creating the duplicate document ID maybe with some whitespace in it which was not visible.
But to rectify I created the data with .set() by generating the document by my own and later while merging data uses the same document ID to merge new fields in the same document ID. and finally it worked.

How to extract specific value from object stored in cloud firestore and get the sum of those values according to needed filters?

I am having an issue in extracting specific value and querying with it. Please guide me on this.
Here is a data structure : (Using flutter/dart and cloudFirestore 3.1.18)
What I want to do is
extract the value of "amount" acccording to "isIncome" (boolean) from all the documents in "entries" collection and get the sum of those extracted amount.
to get the all the "amount" done in a day according to "entryLog" as well and show filtered data (according to date and income type) in listview builder as well.
This is the code I have return for getting all those entries in a stream
Stream<List<Entries>> streamAllEntries() {
var uid = FirebaseAuth.instance.currentUser.uid;
var stream = _db
.collection('entries')
.where("addedBy", isEqualTo: uid)
.orderBy('entryLog', descending: true)
.snapshots()
.map((event) =>
event.docs.map((e) => Entries.fromJson(e.data())).toList());
log(stream.toString());
return stream;
}
and this is my code for Showing DailyReports (here -- entries)
class DailyReports extends StatefulWidget {
const DailyReports({Key? key}) : super(key: key);
#override
State<DailyReports> createState() => _DailyReportsState();
}
class _DailyReportsState extends State<DailyReports> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
body: getBody(),
);
}
Widget getBody() {
var entries = Provider.of<List<Entries>>(context);
var size = MediaQuery.of(context).size;
return Container(
margin: const EdgeInsets.only(bottom: 5),
child: Column(
children: [
//header card
SizedBox(
height: 140,
child: Card(
child: Padding(
padding: const EdgeInsets.only(
top: 10, bottom: 10, right: 10, left: 10),
child:
//header row
Column(
children: [
//title
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Transactions",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 22),
),
Icon(Ionicons.search, color: ColorTheme().blackColor),
],
),
//day tabs
const SizedBox(height: 10),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ListView.builder(
itemCount: days.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
var day = days[index];
return weekTabs(size, index, day);
},
),
),
),
],
),
),
),
),
//income/expense card
incomeExpenseStatus(entries),
testbtn(),
// transaction summary
Expanded(child: transactionSection(entries)),
],
),
);
}
testbtn() {
return IconButton(
onPressed: () async {
await FirestoreService().addToAmountCollection(1000, true, "entry8");
},
icon: const Icon(Icons.mail, color: Colors.white));
}
Card incomeExpenseStatus(List<Entries> entries) {
return Card(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Transaction Summary",
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
Container(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text(
"Income",
style: TextStyle(),
),
const Text(
"Rs. 60000",
style: TextStyle(
color: Colors.green,
fontSize: 16,
fontWeight: FontWeight.bold),
),
Container(
width: 1,
height: 20,
color: Colors.black,
),
const Text(
"Expenses",
),
const Text(
"Rs. 100000",
style: TextStyle(
color: Colors.red,
fontSize: 16,
fontWeight: FontWeight.bold),
),
],
),
),
],
),
),
);
}
Widget transactionSection(List<Entries> entries) {
int? totalAmt;
return Card(
child: Column(
children: [
const SizedBox(height: 5),
Text(
"Transactions count : ${entries.length}",
style: const TextStyle(fontSize: 10, color: Colors.red),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 10),
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: entries.length,
itemBuilder: (context, index) {
var transaction = entries[index];
DateTime d = DateTime.parse(transaction.entryLog);
return Card(
child: ListTile(
//*?How icon color works
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: ((context) => TransactionDetailScreen(
index: transaction)),
),
);
},
leading: CircleAvatar(
child: Center(
child: Icon(
getCategoryWiseIcon(
transaction.details!.category.toString()),
),
),
),
title: Text(transaction.details!.category.toString()),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(transaction.details!.remarks.toString()),
Text("$d"),
],
),
trailing: transaction.details!.isIncome == true
? Text("IN",
style:
TextStyle(color: ColorTheme().greenColor))
: Text("OUT",
style: TextStyle(
color: ColorTheme().primaryColor))),
);
}),
),
),
],
),
);
}
int activeDay = 1;
#override
void initState() {
activeDay = DateTimeExtractor().getDayAsInteger(activeDay);
super.initState();
}
Widget weekTabs(size, index, day) {
log('Active month:$activeDay');
return GestureDetector(
onTap: () {
setState(() {
activeDay = index;
});
},
child: Row(
children: [
Column(
children: [
Text(
day['label'],
style: TextStyle(
fontSize: 12,
color: activeDay == index
? ColorTheme().primaryColor
: ColorTheme().blackColor.withOpacity(0.8),
fontWeight: activeDay == index
? FontWeight.w500
: FontWeight.normal),
),
const SizedBox(height: 5),
Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color: activeDay == index
? ColorTheme().primaryColor
: ColorTheme().whiteColor,
shape: BoxShape.circle,
border: Border.all(color: ColorTheme().primaryColor),
),
child: Center(
child: Text(
day['day'],
style: TextStyle(
fontSize: 12,
color: activeDay != index
? ColorTheme().primaryColor
: ColorTheme().whiteColor,
),
),
),
),
],
),
const SizedBox(width: 20),
],
),
);
}
}
This is my Entres model class
class Entries {
String? addedBy;
Details? details;
String? entryID;
dynamic entryLog;
String? gaadiID;
Entries({
this.addedBy = "",
this.details,
this.entryID = "",
this.entryLog,
this.gaadiID = "",
});
factory Entries.fromJson(Map<String, dynamic> json) =>
_$EntriesFromJson(json);
Map<String, dynamic> toJson() => _$EntriesToJson(this);
Entries _$EntriesFromJson(Map<String, dynamic> json) => Entries(
addedBy: json['addedBy'] as String? ?? "",
details: json['details'] == null
? null
: Details.fromJson(json['details'] as Map<String, dynamic>),
entryID: json['entryID'] as String? ?? "",
entryLog: json['entryLog'].toString(),
gaadiID: json['gaadiID'] as String? ?? "",
);
Map<String, dynamic> _$EntriesToJson(Entries instance) => <String, dynamic>{
'addedBy': instance.addedBy,
'details': instance.details,
'entryID': instance.entryID,
'entryLog': instance.entryLog.toString(),
'gaadiID': instance.gaadiID,
};
}
If you need any more info then please feel free to ask .

Flutter- click is responding to every item in listview.builder

I am trying to create a list of items in flutter with listView.builder, i am also using using elevatedButton in my itemBuilder.
i applied setState in button
i want to change value of single item only
but that is applying to every value in list
here is my code
import 'dart:developer';
import 'package:counter_button/counter_button.dart';
import 'package:flutter/material.dart';
import 'package:fooddeliveryapp/apis.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'models/restrauntmenu.dart';
class RestrauntPage extends StatefulWidget {
final String restrauntId;
final String restrauntName;
final String restrauntType;
final String restrauntApproxBill;
final String restrauntTagline;
const RestrauntPage(
{Key? key,
required this.restrauntId,
required this.restrauntType,
required this.restrauntApproxBill,
required this.restrauntTagline,
required this.restrauntName})
: super(key: key);
#override
State<RestrauntPage> createState() => _RestrauntPageState();
}
class _RestrauntPageState extends State<RestrauntPage> {
int _counterValue = 1;
bool itemAdded = false;
late Future<List<RestrauntMenu>> futureRestrauntMenu;
Future<List<RestrauntMenu>> fetchRestrauntMenu() async {
String restrauntId = widget.restrauntId;
final response = await http.get(Uri.parse(menuApi(restrauntId)));
if (response.statusCode == 200) {
final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
return parsed
.map<RestrauntMenu>((json) => RestrauntMenu.fromMap(json))
.toList();
} else {
throw Exception('Failed to load album');
}
}
addToCartButton(
{required String? itemname,
required String? itemprice,
required int? itemCount,
required String? usermob,
required String? restrauntName}) {
return ElevatedButton(
clipBehavior: Clip.antiAliasWithSaveLayer,
style: ButtonStyle(
elevation: MaterialStateProperty.all(
6,
),
backgroundColor: MaterialStateProperty.all(Colors.white),
),
onPressed: () {
addToCart(
itemname: itemname,
itemprice: itemprice,
restrauntName: restrauntName,
usermob: usermob,
itemCount: itemCount);
},
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'ADD TO CART',
style: TextStyle(
color: Colors.green,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
);
}
counterButton() {
return Container(
decoration: const BoxDecoration(color: Colors.white),
child: CounterButton(
loading: false,
onChange: (int val) {
setState(() {
_counterValue = val;
});
},
count: _counterValue,
countColor: Colors.green,
buttonColor: Colors.black,
progressColor: Colors.black,
),
);
}
Future addToCart(
{required String? itemname,
required String? itemprice,
required int? itemCount,
required String? usermob,
required String? restrauntName}) async {
itemCount = _counterValue;
var url = addToCartApi(
itemname: itemname,
itemprice: itemprice,
itemCount: itemCount,
usermob: usermob,
restrauntName: restrauntName);
var response = await http.get(
Uri.parse(url),
);
if (response.statusCode == 200) {
setState(() {
itemAdded = true;
});
} else {
return false;
}
}
#override
void initState() {
futureRestrauntMenu = fetchRestrauntMenu();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
foregroundColor: Colors.black,
elevation: 0,
backgroundColor: Colors.white,
title: const Text('Restraunt Name'),
),
body: SingleChildScrollView(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.03,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.restrauntName,
style: const TextStyle(
color: Colors.black,
fontSize: 24,
fontWeight: FontWeight.w900,
),
),
// const SizedBox(height: 4),
Text(
widget.restrauntType,
style: const TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.normal,
),
),
Text(
widget.restrauntTagline,
style: const TextStyle(
color: Colors.black87,
fontSize: 12,
fontWeight: FontWeight.normal,
),
),
const SizedBox(
height: 6,
),
Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RichText(
text: TextSpan(
children: [
const WidgetSpan(
child: Icon(
Icons.currency_rupee,
size: 16,
color: Color.fromARGB(255, 45, 174, 49),
),
),
TextSpan(
text: widget.restrauntApproxBill,
style: const TextStyle(
color: Colors.black,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
),
],
),
const Spacer(),
Container(
decoration: BoxDecoration(
color: const Color.fromARGB(255, 49, 171, 53),
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RichText(
text: const TextSpan(
children: [
TextSpan(
text: '3.6',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
WidgetSpan(
child: Icon(
Icons.star,
color: Colors.white,
size: 18,
),
),
],
),
),
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.03,
),
],
),
const SizedBox(
height: 12,
),
Expanded(
child: FutureBuilder<List<RestrauntMenu>>(
future: futureRestrauntMenu,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return ExpansionTile(
initiallyExpanded: true,
childrenPadding: const EdgeInsets.all(8),
title: Text(
snapshot.data![index].catname!,
style: const TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
),
children: [
Row(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
snapshot.data![index].itemname!,
style: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
),
),
const SizedBox(
height: 4,
),
Text(
snapshot.data![index].itemPrice!,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 4,
),
Text(
snapshot.data![index].itemDescription!,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.normal,
),
),
],
),
const Spacer(),
Stack(
alignment: Alignment.bottomCenter,
children: [
Padding(
padding:
const EdgeInsets.only(bottom: 16),
child: ClipRRect(
borderRadius:
BorderRadius.circular(10),
child: FittedBox(
child: Container(
height: MediaQuery.of(context)
.size
.height *
0.22,
width: MediaQuery.of(context)
.size
.width *
0.4,
decoration: BoxDecoration(
color: Colors.red,
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
'http://www.jfamoslogistics.com/images/${snapshot.data![index].itemimage!}',
),
),
),
),
),
),
),
Align(
alignment: Alignment.topRight,
child: itemAdded
? counterButton()
: addToCartButton(
itemprice: snapshot
.data![index].itemPrice,
itemname: snapshot
.data![index].itemname,
itemCount: _counterValue,
restrauntName:
widget.restrauntName,
usermob: '9354954343',
))
],
)
],
),
],
);
},
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return const Center(
child: CircularProgressIndicator(),
);
},
),
),
],
),
),
),
);
}
}
please check and help me
please let me know if i am missing something or making some mistake in code
i have tried google everywhere but nothing works
thanks in advance
As Giseppe Colucci described, you are using a single counter variable for a list . You can follow the simple approach of using list. On State
int _counterValue = 1; will be replaced with List<int> _counterValue = []
After getting data initialize the list with default value.
if (snapshot.hasData) {
_counterValue =List.generate(snapshot.data!.length, (index) => 1); // you might prefer default value as 0 instead of 1
As for the counter button method we need to update specific index, therefore we will pass index here
counterButton(int index) {
return Container(
decoration: const BoxDecoration(color: Colors.white),
child: CounterButton(
loading: false,
onChange: (int val) {
setState(() {
_counterValue[index] = val;
});
},
count: _counterValue[index],
Now whenever we use this counterButton method we need to pass index and here we get index from listview.
child: itemAdded
? counterButton(index)
: addToCartButton(
That is because your itemAdded bool is only one, for every item in the list, you should make a map, like this:
{'id':true}
where id is the restaurant menu item, and true is whenever the item is selected or not.
If this is too hard for you, just use a simple list.

Flutter - codes not working correctly after putting inside setState

I am trying to add to an array list after user clicked. I am using InkWell, onTap function.
child: InkWell(
onTap: () {
if (tempArray.contains(entries[index].toString())) {
tempArray.remove(entries[index].toString());
print(tempArray.toList().toString());
} else {
tempArray.add(entries[index].toString());
print(tempArray.toList().toString());
}
My debug console is printing these out,
enter image description here
However, when i put the codes inside a setState, this is what got printed
child: InkWell(
onTap: () {
setState(() {
if (tempArray.contains(entries[index].toString())) {
tempArray.remove(entries[index].toString());
print(tempArray.toList().toString());
} else {
tempArray.add(entries[index].toString());
print(tempArray.toList().toString());
}
});
enter image description here
What i am trying to do, is to show/hide the 'trailing' icon in the ListTile, based on whatever user had selected the particular item.
My full codes (without the setState) are as follows,
import 'package:flutter/material.dart';
class Personal1Redo extends StatefulWidget {
#override
_Personal1RedoState createState() => _Personal1RedoState();
}
class _Personal1RedoState extends State<Personal1Redo> {
#override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
List<String> entries = [
'Residental Loan',
'Personal Loan',
'Car Loan',
'Renovation Loan',
'Savings Account',
];
List<String> tempArray = [];
final heading = Column(
children: [
const SizedBox(
height: 40,
),
SizedBox(
height: (mediaQuery.size.height - mediaQuery.padding.top) * 0.1,
child: const Align(
alignment: Alignment.center,
child: Text(
'What do you aspire to do?',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
),
),
const SizedBox(
height: 20,
),
],
);
return Scaffold(
appBar: AppBar(
title: Text('Borrower redo'),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
heading,
ListView.builder(
shrinkWrap: true,
itemCount: entries.length,
itemBuilder: (ctx, index) {
return Container(
width: mediaQuery.size.width * 0.9,
padding: const EdgeInsets.all(15),
child: InkWell(
onTap: () {
if (tempArray.contains(entries[index].toString())) {
tempArray.remove(entries[index].toString());
print(tempArray.toList().toString());
} else {
tempArray.add(entries[index].toString());
print(tempArray.toList().toString());
}
},
child: Card(
margin: const EdgeInsets.all(10),
elevation: 8,
child: ListTile(
title: Text(
entries[index],
style: TextStyle(
color: Colors.grey.shade800,
fontSize: 20,
),
textAlign: TextAlign.center,
),
trailing: tempArray.contains(entries[index])
? Icon(Icons.check_box_outline_blank_outlined)
: null,
),
),
),
);
})
],
),
),
);
}
}
Any helps and guidance is very much appreciated, thanks!!
Define variables and functions outside build method.
As setState method, calls build, every time it is called.
Like this :
import 'package:flutter/material.dart';
class Personal1Redo extends StatefulWidget {
#override
_Personal1RedoState createState() => _Personal1RedoState();
}
class _Personal1RedoState extends State<Personal1Redo> {
List<String> entries = [
'Residental Loan',
'Personal Loan',
'Car Loan',
'Renovation Loan',
'Savings Account',
];
List<String> tempArray = [];
getHeadingWidget(BuildContext context) {
return Column(
children: [
const SizedBox(
height: 40,
),
SizedBox(
height: (mediaQuery!.size.height - mediaQuery.padding.top) * 0.1,
child: const Align(
alignment: Alignment.center,
child: Text(
'What do you aspire to do?',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
),
),
const SizedBox(
height: 20,
),
],
);
}
#override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
return Scaffold(
appBar: AppBar(
title: Text('Borrower redo'),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
getHeadingWidget(context),
ListView.builder(
shrinkWrap: true,
itemCount: entries.length,
itemBuilder: (ctx, index) {
return Container(
width: mediaQuery.size.width * 0.9,
padding: const EdgeInsets.all(15),
child: InkWell(
onTap: () {
if (tempArray.contains(entries[index].toString())) {
tempArray.remove(entries[index].toString());
print(tempArray.toList().toString());
} else {
tempArray.add(entries[index].toString());
print(tempArray.toList().toString());
}
},
child: Card(
margin: const EdgeInsets.all(10),
elevation: 8,
child: ListTile(
title: Text(
entries[index],
style: TextStyle(
color: Colors.grey.shade800,
fontSize: 20,
),
textAlign: TextAlign.center,
),
trailing: tempArray.contains(entries[index])
? Icon(Icons.check_box_outline_blank_outlined)
: null,
),
),
),
);
})
],
),
),
);
}
}

No data from sever API's is not showing on Listview using flutter

I'm fetching data from server APIs, The data is being successfully fetched from the server but the issue is that when the data is provided to Listview it cant be shown. How can I show the data on Listview in a flutter/dart?
Following is the code for fetching data from server API's
List<String> jobTitles = [];
List officeNames = [ ];
List officeLocations = [ ];
List jobTypes = [ ];
Future getJobsData() async {
var response = await http
.get(Uri.https('hospitality92.com', 'api/jobsbycategory/All'));
Map<String, dynamic> map = json.decode(response.body);
List<dynamic> jobData = map["jobs"];
if (jobTitles.length != 0) {
officeNames.clear();
jobTitles.clear();
officeLocations.clear();
jobTypes.clear();
}
for (var i = 0; i < jobData.length; i++) {
jobTitles.add(jobData[i]["title"]);
officeNames.add(jobData[i]["company_name"]);
officeLocations.add(jobData[i]["company_name"]);
jobTypes.add(jobData[i]["type"]);
}
/* print(jobTitles);
print(officeNames);
print(officeLocations);
print(jobTypes);*/
}
Here is the design code that I wanted to show:
Widget listCard(jobTitle, officeName, location, jobType, onPress) {
return Container(
child: InkWell(
onTap: onPress,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xC000000), Color(0xC000000)])),
child: ListTile(
leading: CircleAvatar(
radius: 30,
child: Image.asset(
"assets/ic_login.png",
height: 28,
width: 28,
),
),
title: Text(
jobTitle,
style: TextStyle(
fontSize: 16,
color: Colors.lightBlue,
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500),
),
subtitle: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Row(
children: [
Icon(
Icons.home_outlined,
color: Colors.black,
size: 16,
),
Text(
officeName,
style: TextStyle(fontSize: 10),
),
],
),
SizedBox(
width: 10,
),
Row(
children: [
Icon(
Icons.location_pin,
color: Colors.blueGrey,
size: 16,
),
SizedBox(
width: 2,
),
Text(
location,
style: TextStyle(fontSize: 10),
),
],
),
SizedBox(
width: 10,
),
Row(
children: [
Container(
margin: const EdgeInsets.fromLTRB(0, 4, 0, 0),
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
Colors.lightBlueAccent,
Colors.lightBlueAccent
])),
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
jobType,
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.bold,
color: Colors.white),
),
),
),
],
)
//ElevatedButton(onPressed: () { }, child: Text("Full Time", style: TextStyle(fontSize: 10),),),
],
),
),
),
),
),
],
),
),
);
}
Here is the listview code
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: jobTitle.length,
itemBuilder: (context, index) {
return listCard(jobTitles[index], officeNames[index],
officeLocations[index], jobTypes[index], () {});
}),
If I provide the static data to list it will show on listview, but dynamic data is not being shown.
Try To below Code Your problem has been solved:
Create API Call Function
Future<List<dynamic>> getJobsData() async {
String url = 'https://hospitality92.com/api/jobsbycategory/All';
var response = await http.get(Uri.parse(url), headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
});
return json.decode(response.body)['jobs'];
}
Write/Create your Widget :
Center(
child: FutureBuilder<List<dynamic>>(
future: getJobsData(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
var title = snapshot.data[index]['title'];
var company = snapshot.data[index]['company_name'];
var skills = snapshot.data[index]['skills'];
var description = snapshot.data[index]['description'];
var positions = snapshot.data[index]['positions'];
return Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.green.shade300,
),
borderRadius: BorderRadius.circular(15.0),
),
child: ListTile(
leading: Text(skills),
title: Text(title),
subtitle: Text(
company + '\n' + description,
),
trailing: Text(positions),
),
);
},
),
);
}
return CircularProgressIndicator();
},
),
),
Your Screen Look Like