flutter dismissible items not removing from listtile - flutter

i have a project about basic market app
first screen adds item to market when clicked on add button adds to some collection and passes to market cart page
in cart page lists the collection (item name,item price,quantity) and bottom of the screen shows total price.
im learning flutter and my coding is pretty bad right now
my problem is im dismissing items but items not removing from the screen. i tried unique key(does nothing and not working), i tried give keys manually this time ''A dismissed Dismissible widget is still part of the tree.''
i tried to remove items from lists that containts data but not working.
this is my seperated listview builder
Widget buildList() => ListView.separated(
separatorBuilder: (context, index) => Divider(
color: Colors.black,
),
itemCount: cartItemQuantity.length,
itemBuilder: (context, index) {
return seperated(
context,
cartItemNames[index],
recievedShopItemsList[index],
index,
cartItemQuantity[index],
recievedShopItemKeys[index],
);
},
);
this is my widget (when its dismissed its gonna remove item and update total price from screen(newPrice) )
Widget seperated(BuildContext context, String name, String price, int index, int quantity, String uKey) {
return Dismissible(
key: Key(uKey),
direction: DismissDirection.endToStart,
onDismissed: (direction) {
widget.recievedCart.remove(name);
widget.recievedNewShopItems.remove(name);
setState(() {
newPrice= newPrice- (int.parse(price) * quantity);
});
},
child: ListTile(
title: Text(
name,
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text("${price}.0 TL"),
trailing: Text("Quantiy : ${quantity}")),
);
im so swamped this is my full code of cart page
Map<String, dynamic> recievedCart = Map();
Map<String, dynamic> recievedShopItems = Map();
Map<String, dynamic> recievedNewShopItems = Map();
CartPage(
{required this.recievedCart,
required this.recievedShopItems,
required this.recievedNewShopItems});
#override
_CartPageState createState() => _CartPageState();
}
class _CartPageState extends State<CartPage> {
var cartItemQuantity,
cartItemNames,
recievedShopItemsList,
recievedShopItemKeys;
num newPrice= 0;
num calculate() {
for (int i = 0; i < widget.recievedNewShopItems.length; i++) {
newPrice= newPrice+
(int.parse(recievedShopItemsList[i]) * cartItemQuantity[i]);
}
return newPrice;
}
#override
void initState() {
// TODO: implement initState
cartItemQuantity = widget.recievedCart.values.toList();
cartItemNames = widget.recievedCart.keys.toList();
recievedShopItemsList = widget.recievedNewShopItems.values.toList();
recievedShopItemKeys = widget.recievedNewShopItems.keys.toList();
setState(() {
newPrice = calculate();
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () {
Navigator.pop(context);
},
),
title: Center(
child: Text("Cart"),
),
),
body: Column(
children: <Widget>[
Expanded(child: buildList()),
Container(
height: MediaQuery.of(context).size.height / 12,
color: Colors.blue,
child: Center(
child: Text(
"TOTAL : ${newPrice}.0 TL",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 25),
),
),
)
],
),
);
}
int a = 0;
int b = 0;
int finalprice= 0;
Widget seperated(BuildContext context, String name, String price, int index,
int quantity, String uKey) {
int qnt = 0;
return Dismissible(
key: Key(uKey), //
direction: DismissDirection.endToStart,
onDismissed: (direction) {
print(uKey);
widget.recievedCart.remove(name);
widget.recievedNewShopItems.remove(name);
setState(() {
newPrice= newPrice- (int.parse(price) * quantity);
});
},
child: ListTile(
title: Text(
name,
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text("${price}.0 TL"),
trailing: Text("Quantiy : ${quantity}")),
);
}
int index = 0;
int itemCount = 0;
Widget buildList() => ListView.separated(
separatorBuilder: (context, index) => Divider(
color: Colors.black,
),
itemCount: cartItemQuantity.length,
itemBuilder: (context, index) {
return seperated(
context,
cartItemNames[index],
recievedShopItemsList[index],
index,
cartItemQuantity[index],
recievedShopItemKeys[index],
);
},
);
}

Change widget.recievedCart.remove(name) to widget.recievedCart.removeAt(index),
remove and removeAt are different:
remove(element)
removes a single element from the list, which is strictly equal to the element passed in.
removeAt(element)
removes the element from the list at the given index, and returns that element

Related

RangeError (index): Invalid value: Not in inclusive range 0..3: 4 when i try to retrieve all list items from firestore

I've been working on a project in part of it I needed to bring a list of data and do some filtering on it, some of those filters are just working fine but I've been facing that problem where the part of getting all the data when I press the button all retrieve all the items of the list and show them into listview.builder() with different Card shapes based on grouping similar data i.e a card designed for data.type[tests] & another card designed for data.type[offers] ..etc.
So when I press all button it shows only the first 4 items inside the listview + it doesn't show data in the card design that supposed to have base on it's group filtering.
here I'm getting the data from firestore
import 'package:cloud_firestore/cloud_firestore.dart';
class Test{
final String details;
final String name;
final String price;
final String type;
Test({
this.details,
this.name,
this.price,
this.type,
});
factory Test.fromDocument(DocumentSnapshot doc){
return Test(
details: doc.data()['details'],
name: doc.data()['name'],
price: doc.data()['price'],
type: doc.data()['type'],
);
}
}
..........................
import 'package:ilab/services/User.dart';
class Services {
final _db = FirebaseFirestore.instance.collection('tests');
// test list from snapshot
List<Test> _testsListFromSnapshot(QuerySnapshot snapshot) {
return snapshot.docs.map((doc) {
return Test(
details: doc.data()['details'] ?? '',
name: doc.data()['name'] ?? '',
price: doc.data()['price'] ?? '',
type: doc.data()['type'] ?? '');
}).toList();
}
// Get tests stream
Stream<List<Test>> get Tests {
return _db.snapshots().map(_testsListFromSnapshot);
}
my component starts here
List<String> alphabets = [
'all',
'a',
'b',
'c',
'd',
... etc
]
List<Test> filteredTests = List();
List<Test> tests = List();
Color color = KWhiteColor;
int Index;
#override
void initState() {
super.initState();
filteredTests = tests;
}
here is the code of giving a card desgin based on the type of data
// return different cardshape for different group of data
Widget _card(int index) {
if (filteredTests
.where((user) => user.type.toLowerCase().contains('باقة'))
.toList()
.isNotEmpty) {
return PackageCardDesign(
packageName: filteredTests[index].name,
price: '${filteredTests[index].price} YR',
details: filteredTests[index].details.toLowerCase(),
colour: Packgecolors[index],
icon: Icons.ac_unit_outlined,
type: filteredTests[index].type,
);
} else if (filteredTests
.where((user) => user.type.toLowerCase().contains('تحليل'))
.toList()
.isNotEmpty) {
return TestCardDesign(
colour: TestOffercolors[index],
testName: filteredTests[index].name,
details: filteredTests[index].details.toLowerCase(),
price: '${filteredTests[index].price} YR',
type: filteredTests[index].type,
);
} else if (filteredTests
.where((user) => user.type.toLowerCase().contains('عرض'))
.toList()
.isNotEmpty) {
return OfferCardDesign(
colour: TestOffercolors[index],
testName: filteredTests[index].name,
// details: filteredUsers[index].details.toLowerCase(),
price: '${filteredTests[index].price} %',
// type: filteredUsers[index].type,
);
}
}
here is the code of creating and printing the top three buttons
ReusableTestChip mainThreeButtonChip(
{#required String text, String buttonName, Function onTap}) {
return ReusableTestChip(
ontap: onTap,
cardChild: Text(
text,
textAlign: TextAlign.center,
style: TextStyle(
color: selectedButton == buttonName ? KWhiteColor : KInActiveColor,
fontSize: 18.0, //25.0,
fontFamily: 'Cairo-Italic',
fontWeight: FontWeight.w600,
),
),
colour: selectedButton == buttonName ? KInActiveColor : KWhiteColor,
);
}
// print Main Three Top Button method using for loop to iterate through loop of strings
List<ReusableTestChip> printMainThreeButtonMethod() {
List<ReusableTestChip> allButtons = [];
for (int i = 0; i < buttons.length; i++) {
String button = buttons[i];
var newItem = mainThreeButtonChip(
text: button,
onTap: () {
setState(() {
selectedButton = buttons[i];
if (buttons[i] == 'تحاليل') {
// setState(() {
// _card = offerList();
// });
filteredTests = tests
.where((u) => (u.type.toLowerCase().contains('تحليل')))
.toList();
} else if (buttons[i] == 'عروض') {
filteredTests = tests
.where((u) => (u.type.toLowerCase().contains('عرض')))
.toList();
} else if (buttons[i] == 'باقات') {
filteredTests = tests
.where((u) => (u.type.toLowerCase().contains('باقة')))
.toList();
}
});
},
buttonName: buttons[i],
);
allButtons.add(newItem);
}
return allButtons;
}
here is the code of creating and printing the all button
ReusableAlphabetChip alphabetChip(
{#required String text, String char, Function onTap}) {
return ReusableAlphabetChip(
ontap: onTap,
cardChild: Text(
text,
textAlign: TextAlign.center,
style: TextStyle(
color: selectedAlphabet == char ? KInActiveColor : KSecondaryColor,
fontSize: 18.0, //25.0,
fontFamily: 'Cairo-Italic',
fontWeight: FontWeight.w600,
),
),
colour: selectedAlphabet == char ? KWhiteColor : KInActiveColor,
);
}
// print all button
List<ReusableAlphabetChip> printAlphabetMethod() {
List<ReusableAlphabetChip> chars = [];
for (int i = 0; i < alphabets.length; i++) {
String char = alphabets[i];
var newItem = alphabetChip(
text: char,
onTap: () {
setState(() {
selectedAlphabet = alphabets[i];
if (alphabets[i] == 'الكل') {
filteredTests = tests;
// _foundUsers = _allUsers;
} else {
filteredTests = tests
.where((u) => (u.name.toLowerCase().startsWith(alphabets[i])))
.toList(); //json filter first filter && firebase second filter
// _foundUsers = _allUsers.where((u) => (u["name"].toLowerCase().startsWith(alphabets[i]))).toList();
}
});
},
char: alphabets[i],
);
chars.add(newItem);
}
return chars;
}
#override
Widget build(BuildContext context) {
tests = Provider.of<List<Test>>(context);
ScrollController scrollController = ScrollController(
initialScrollOffset: 10, // or whatever offset you wish
keepScrollOffset: true,
);
return SafeArea(
child: Scaffold(
appBar: AppBar(
toolbarHeight: 100,
title: Image.asset('images/logo.jpeg',
height: 100.0, alignment: Alignment.center),
),
drawer: AppDrawer(),
body: ListView(
shrinkWrap: true,
children: [
// applogo(),
Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: 10.0),
Row(
// top filters
mainAxisAlignment: MainAxisAlignment.center,
children: printMainThreeButtonMethod(),
),
Container(
// get all list items
margin: EdgeInsets.symmetric(vertical: 4.0),
height: 50.0,
child: ListView(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
children: printAlphabetMethod()),
),
SizedBox(
height: 390,
child: Column(
children: [
Expanded(
child: ListView.builder(
shrinkWrap: true,
padding: EdgeInsets.all(10.0),
controller: scrollController,
scrollDirection: Axis.vertical,
itemCount: filteredUsers.length,
itemBuilder: (BuildContext context, int index) {
Index = index;
if (index < filteredTests.length) {
return Card(
child: Padding(
padding: EdgeInsets.all(10.0),
child:_card(Index)
),
);
} else {
return Center(child: CircularProgressIndicator());
}
},
// itemCount: filteredUsers.length + 1,
),
),
],
),
),
],
),
],
),
bottomNavigationBar: MyBottomBar(),
),
);
}
I hope I explained what I'm facing clearly, any help will be appreciated and thanks in advance.
I found out that the problem was in color's list. where I made a list of colors to allow ListView.builder prints Cards of data that will retrieve with different colors, it turns out that due to color's list is finite and when the ListView.builder reaches the end of it, it returns that error [RangeError (index): Invalid value: Not in inclusive range 0..3: 4], So I've made a change on my color's list so when it reaches the end of the list it start over from the beginning and printing new data using the specified colors, like this
Color selectedColour(index) {
Color c;
if (index % 4 == 0) c = Colors.cyan;
if (index % 4 == 1) c = Colors.blueGrey;
if (index % 4 == 2) c = Colors.blue;
if (index % 4 == 3) c = Color(0xFFea9999);
return c;
}
this is my previous color's list before changing it
var Paccolors = [
Colors.blue,
Colors.cyan,
Colors.blueGrey,
Colors.pink,
Colors.black45,
Colors.lightGreen,
Colors.green,
Colors.red
];

Flutter Refresh grid view with selected item

I have a flutter grid view with multiple selection.
Each time I select an item, it goes inside the SelectedList and i can see a blue tick on each element.
But each time I add a new element, I update the the list and the Consumer receive the notification, I can see the new elements but I lost all the previous selected item.
Only the GridItemCustom is impacted for the CustomExercises.
Does someone has an idea, on how to keep the previous selected elements?
it look like that once the new list is updated, i have to check if the image has been selected or not..
In the video, I select 'Superman' and then add 'Test145', then I lost the selected item 'Superman'...
Future<void> updateOnceCustomExercisesList() async {
return this._memoizer.runOnce(() async {
List<ExerciseItem> newList = await dbHelper!
.findCustomExercises(widget.status == "cooldown" ? true : false);
exerciseLoader.updateList(newList); -> does nofify ExerciseLoader Consumer
});
}
Text('Custom Exercises'),
FutureBuilder(
future: updateOnceCustomExercisesList(),
builder:
(BuildContext context, AsyncSnapshot<void> snapshot) {
if (snapshot.hasError) {
print("ERROR\n");
}
switch (snapshot.connectionState) {
case ConnectionState.done:
return Container();
default:
return buildLoadingScreen();
}
},
),
Consumer<ExerciseLoader>(
builder: (context, customExercises, child) =>
GridView.builder(
shrinkWrap: true,
physics: ScrollPhysics(),
itemCount:
customExercises.getCustomExercises().length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
childAspectRatio: 0.56,
crossAxisSpacing: 2,
mainAxisSpacing: 2),
itemBuilder: (context, index) {
return GridItemCustom(
item: customExercises
.getCustomExercises()
.elementAt(index),
isSelected: (bool value) {
setState(() {
if (value) {
widget.selectedList.add(customExercises
.getCustomExercises()
.elementAt(index));
} else {
widget.selectedList.remove(customExercises
.getCustomExercises()
.elementAt(index));
}
});
print("$index : $value");
},
key: Key(customExercises
.getCustomExercises()
.elementAt(index)
.uniqueKey
.toString()));
}),
),
My GridCustomItem is like:
class GridItemCustom extends StatefulWidget {
final Key key;
final ExerciseItem item;
final ValueChanged<bool> isSelected;
GridItemCustom(
{required this.item, required this.isSelected, required this.key});
String get2FirstLetters(String str) {
String initial = "";
List<String> words = str.split(" ");
for (int i = 0; i < words.length; i++) {
initial += words[i].substring(0, 1);
}
return initial.toUpperCase();
}
#override
_GridItemCustomState createState() => _GridItemCustomState();
}
class _GridItemCustomState extends State<GridItemCustom> {
bool isSelected = false;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
setState(() {
isSelected = !isSelected;
widget.isSelected(isSelected);
});
},
child: Column(
children: <Widget>[
Stack(alignment: Alignment.bottomRight, children: <Widget>[
CircleAvatar(
backgroundColor: Colors.black.withOpacity(isSelected ? 0.9 : 0),
child: Text(widget.get2FirstLetters(widget.item.title)),
),
isSelected
? Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Icon(
Icons.check_circle,
color: Colors.blue,
)),
)
: Container(),
]),
SizedBox(height: 10),
Text(
widget.item.title,
style: TextStyle(
color: Colors.orange,
fontFamily: 'LibreBaskerville',
fontSize: 10),
),
//: Container()
],
),
);
}
}
Thanks for your time

Exporting a Flutter List to CSV file

I have this screen which lists the items of a class into ListView. What I would want is to have the button (FloatingActionButton in the code) that would export that list to a CSV file. I have the code of what I think it should look, but my issue is that I don't know how to use onPressed on the button in order to export, for now it is null, but it should call the getCSV() function with something in it. Here's the code:
class MailListAdmin extends StatefulWidget {
#override
_MailListAdminState createState() => _MailListAdminState();
}
class _MailListAdminState extends State<MailListAdmin> {
List<String> list = [];
List<Email> finalExport;
#override
void initState() {
super.initState();
DatabaseProvider.db.getMail().then(
(mailList) {
BlocProvider.of<MailBloc>(context).add(SetMail(mailList));
},
);
}
getCsv(List<Email> mailList) async {
List<List<dynamic>> rows = List<List<dynamic>>();
for (int i = 0; i < mailList.length; i++) {
List<dynamic> row = List();
row.add(mailList[i].id);
row.add(mailList[i].email);
rows.add(row);
setState(() {
mailList = finalExport;
});
print(rows);
}
await SimplePermissions.requestPermission(Permission.WriteExternalStorage);
bool checkPermission = await SimplePermissions.checkPermission(
Permission.WriteExternalStorage);
if (checkPermission) {
String dir =
(await getExternalStorageDirectory()).absolute.path + "/documents";
String file = "$dir";
File f = new File(file + "filename.csv");
String csv = const ListToCsvConverter().convert(rows);
f.writeAsString(csv);
}
}
//-------------------------------------
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blueGrey[900],
title: Text('Newsletter Users'),
actions: [
Padding(
padding: EdgeInsets.only(right: 20.0),
child: Badge(
child: Text('Copied ' + list.length.toString()),
showBadge: false)),
],
),
body: Container(
child: BlocConsumer<MailBloc, List<Email>>(
builder: (context, mailList) {
return ListView.separated(
itemCount: mailList.length,
itemBuilder: (BuildContext context, int index) {
Email mail = mailList[index];
return Card(
child: ListTile(
leading: GestureDetector(
child: Icon(Icons.copy),
onTap: () {
FlutterClipboard.copy(mail.email);
print('Copied ${mail.email}!');
Scaffold.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.grey[600],
duration: Duration(milliseconds: 1000),
content: Text(
'${mail.email} Copied To Clipboard!',
style: TextStyle(fontSize: 20.0),
),
));
list.add(mail.email);
setState(() {
list.length.toString();
});
print(mail.email);
print(list);
}),
trailing: Icon(Icons.delete),
onTap: () {
DatabaseProvider.db.deleteMail(mail.id).then((_) {
BlocProvider.of<MailBloc>(context).add(
DeleteMail(index),
);
});
list.remove(mail.email);
print(list);
setState(() {
list.length.toString();
});
},
title: Text(
mail.email,
style: TextStyle(fontSize: 20.0),
),
),
);
},
separatorBuilder: (BuildContext context, int index) =>
Divider(color: Colors.black),
);
},
listener: (BuildContext context, mailList) {},
),
),
floatingActionButton: FloatingActionButton(
child: Text('Export'),
onPressed: () =>
null, //im not sure how to add the mailList to getCsv(???)
),
);
}
}
Check the export button, where I am not sure how to activate it with getCSV function. Also, how would I access the saved CSV file after it is saved (where would it be saved in the device?)
Try the following steps:
Create a new list in the class.
Assign it to the mail list from the BlocConsumer.
Then use the list in onPressed by passing it to getCsv method.
The Implementation
theEmails is the new list.
class _MailListAdminState extends State<MailListAdmin> {
List<String> list = [];
List<Email> finalExport;
#override
void initState() {
super.initState();
DatabaseProvider.db.getMail().then(
(mailList) {
BlocProvider.of<MailBloc>(context).add(SetMail(mailList));
},
);
}
List<Email> theEmails = [];
getCsv(List<Email> mailList) async {
List<List<dynamic>> rows = List<List<dynamic>>();
for (int i = 0; i < mailList.length; i++) {
List<dynamic> row = List();
row.add(mailList[i].id);
row.add(mailList[i].email);
rows.add(row);
setState(() {
mailList = finalExport;
});
print(rows);
}
await SimplePermissions.requestPermission(Permission.WriteExternalStorage);
bool checkPermission = await SimplePermissions.checkPermission(
Permission.WriteExternalStorage);
if (checkPermission) {
String dir =
(await getExternalStorageDirectory()).absolute.path + "/documents";
String file = "$dir";
File f = new File(file + "filename.csv");
String csv = const ListToCsvConverter().convert(rows);
f.writeAsString(csv);
}
}
//-------------------------------------
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blueGrey[900],
title: Text('Newsletter Users'),
actions: [
Padding(
padding: EdgeInsets.only(right: 20.0),
child: Badge(
child: Text('Copied ' + list.length.toString()),
showBadge: false)),
],
),
body: Container(
child: BlocConsumer<MailBloc, List<Email>>(
builder: (context, mailList) {
theEmails = mailList;
return ListView.separated(
itemCount: mailList.length,
itemBuilder: (BuildContext context, int index) {
Email mail = mailList[index];
return Card(
child: ListTile(
leading: GestureDetector(
child: Icon(Icons.copy),
onTap: () {
FlutterClipboard.copy(mail.email);
print('Copied ${mail.email}!');
Scaffold.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.grey[600],
duration: Duration(milliseconds: 1000),
content: Text(
'${mail.email} Copied To Clipboard!',
style: TextStyle(fontSize: 20.0),
),
));
list.add(mail.email);
setState(() {
list.length.toString();
});
print(mail.email);
print(list);
}),
trailing: Icon(Icons.delete),
onTap: () {
DatabaseProvider.db.deleteMail(mail.id).then((_) {
BlocProvider.of<MailBloc>(context).add(
DeleteMail(index),
);
});
list.remove(mail.email);
print(list);
setState(() {
list.length.toString();
});
},
title: Text(
mail.email,
style: TextStyle(fontSize: 20.0),
),
),
);
},
separatorBuilder: (BuildContext context, int index) =>
Divider(color: Colors.black),
);
},
listener: (BuildContext context, mailList) {},
),
),
floatingActionButton: FloatingActionButton(
child: Text('Export'),
onPressed: (){
getCsv(theEmails);
}, //im not sure how to add the mailList to getCsv(???)
),
);
}
}

price from each item from listview into Total price is runing more than once,which is not the correct . How to run it once

My listview total price code is runing more than once which is adding to the price variable again which is not the correct value ,how to prevent it from runing twice . As per my research my future builder is in build method ,if this is the problem then how to do it ,or any other suggestion would be great.
import 'package:flutter/material.dart';
import 'package:restaurant_ui_kit/models/user.dart';
import 'package:restaurant_ui_kit/screens/checkout.dart';
import 'package:restaurant_ui_kit/util/database_helper.dart';
class CartScreen extends StatefulWidget {
#override
_CartScreenState createState() => _CartScreenState();
}
class _CartScreenState extends State<CartScreen>
with AutomaticKeepAliveClientMixin<CartScreen> {
var db = new DatabaseHelper();
static int subTotal = 0;
List _users = [];
#override
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
body: Padding(
padding: EdgeInsets.fromLTRB(10.0, 0, 10.0, 0),
child: FutureBuilder<List>(
future: db.getAllUsers(),
initialData: List(),
builder: (context, snapshot) {
return snapshot.hasData
? ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, position) {
final item = snapshot.data[position];
for (int i = 0; i < snapshot.data.length; i++) {
subTotal = subTotal +
int.parse(
User.fromMap(snapshot.data[position]).price);
}
print('toatl is $subTotal');
// get your item data here ...
return Dismissible(
key: UniqueKey(),
child: new Card(
color: Colors.white,
elevation: 2.0,
child: new ListTile(
leading: new CircleAvatar(
child: Text(
"${User.fromMap(snapshot.data[position]).name.substring(0, 1)}"),
),
title: new Text(
"User: ${User.fromMap(snapshot.data[position]).price}"),
subtitle: new Text(
"Id: ${User.fromMap(snapshot.data[position]).id}"),
onTap: () => debugPrint(
"${User.fromMap(snapshot.data[position]).id}"),
),
),
background: slideLeftBackground(),
confirmDismiss: (direction) async {
if (direction == DismissDirection.endToStart) {
final bool res = await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Text(
"Are you sure you want to delete ${User.fromMap(snapshot.data[position]).name}?"),
actions: <Widget>[
FlatButton(
child: Text(
"Cancel",
style: TextStyle(color: Colors.black),
),
onPressed: () {
Navigator.of(context).pop();
},
),
FlatButton(
child: Text(
"Delete",
style: TextStyle(color: Colors.red),
),
onPressed: () {
// TODO: Delete the item from DB etc..
setState(() {
// total();
// print(position);
if (position == 0) {
//print('index 0 dai');
db.deleteUser(User.fromMap(
snapshot.data[position])
.id);
//snapshot.data.removeAt(position);
} else {
snapshot.data
.removeAt(--position);
db.deleteUser(User.fromMap(
snapshot.data[position])
.id);
}
//print("removed");
// print('mSubTotal $mSubTotal');
});
Navigator.of(context).pop();
},
),
],
);
});
return res;
}
},
);
},
)
: Center(
child: CircularProgressIndicator(),
);
},
),
),
floatingActionButton: FloatingActionButton(
tooltip: "Checkout",
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return Checkout();
},
),
);
},
child: Icon(
Icons.arrow_forward,
),
heroTag: Object(),
),
);
}
#override
bool get wantKeepAlive => true;
}
Widget slideLeftBackground() {
return Container(
color: Colors.red,
child: Align(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Icon(
Icons.delete,
color: Colors.white,
),
Text(
" Delete",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700,
),
textAlign: TextAlign.right,
),
SizedBox(
width: 20,
),
],
),
alignment: Alignment.centerRight,
),
);
}
subTotal is printing like this in terminal the correctvalue is 500 because each item has price of 100 and there are 5 items but as you all know the last value is assigned to the variable
I/flutter ( 3885): Count : 5
I/flutter ( 3885): toatl is 500
I/flutter ( 3885): toatl is 1000
I/flutter ( 3885): toatl is 1500
I/flutter ( 3885): toatl is 2000
I/flutter ( 3885): toatl is 2500
You sum and add values every time build method run. You can reset the subTotal every time or there is a shorter way to sum the values, you can try it; instead of using;
for (int i = 0; i < snapshot.data.length; i++) {
subTotal = subTotal +
int.parse(
User.fromMap(snapshot.data[position]).price);
}
just try this;
subTotal = snapshot.data.fold(0, (previousValue, element) => previousValue + int.tryParse(User.fromMap(item).price));

Flutter Firebase RTDB issue retrieving specific child

I have tried to retrieve data from a specific child from Firebase RTDB. The problem is that the following error appears (I don't use int):
Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index'
The log says that the error appears here
DATA[individualKey]['name'],
DATA[individualKey]['picture'],
DATA[individualKey]['price'],
DATA[individualKey]['id'],
DATA[individualKey]['brand'],
DATA[individualKey]['category'],
// DATA[individualKey]['feature'],
// DATA[individualKey]['sale'],
// DATA[individualKey]['colors'],
// DATA[individualKey]['sizes'],
DATA[individualKey]['quantity'],
The code that I am going to show, I use it on another screen with minimal changes and it works
but in the current one that I use it doesn't work
class PostsDetails extends StatefulWidget {
final value2;
PostsDetails({Key key,#required this.value2}) : super(key : key);
#override
_PostsDetailsState createState() => _PostsDetailsState(value2);
}
class _PostsDetailsState extends State<PostsDetails> {
final value2;
_PostsDetailsState(this.value2);
List<Posts>postsList = [];
#override
void initState() {
// TODO: implement initState
super.initState();
DatabaseReference postsRef = FirebaseDatabase.instance.reference().child("Product").child("Shoes").child("Nike").child(value2);
postsRef.once().then((DataSnapshot snap)
{
var KEYS = snap.value.keys;
var DATA = snap.value;
postsList.clear();
for(var individualKey in KEYS)
{
Posts posts = new Posts
(
DATA[individualKey]['name'],
DATA[individualKey]['picture'],
DATA[individualKey]['price'],
DATA[individualKey]['id'],
DATA[individualKey]['brand'],
DATA[individualKey]['category'],
// DATA[individualKey]['feature'],
// DATA[individualKey]['sale'],
// DATA[individualKey]['colors'],
// DATA[individualKey]['sizes'],
DATA[individualKey]['quantity'],
);
postsList.add(posts);
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.1,
backgroundColor: Colors.red,
title: InkWell(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context)=> new HomePage()));
},
child: Text("SHOP APP")),
actions: <Widget>[
new IconButton(icon: Icon(Icons.search, color: Colors.white,), onPressed: (){}),
],
),
body: new ListView(
children: <Widget>[
new Container(
child: postsList.length == 0 ? new Text("No Available"):new ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: postsList.length,
itemBuilder: (_, index){
new Container(
height: 300.0,
child: GridTile(
child: Container(
color: Colors.white,
// child: Image.network(postsList[index].picture),
),
footer: new Container(
color: Colors.white70,
child: ListTile(
leading: new Text(postsList[index].name,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0),),
title: new Row(
children: <Widget>[
Expanded(
// child: new Text("\$"+postsList[index].price, style: TextStyle(fontWeight: FontWeight.bold, color: Colors.red),)
),
],
),
),
),
),
);
})
),
]
)
);
}
}
postslist.length retrieves 0.
final value2 its a child ID. I have verified that it is received well from the previous screen
and if value2 is not used, data will not be retrieved
Posts Class:
class Posts
{
String name;
String picture;
String price;
String id;
String brand;
String category;
String quantity;
// List<> colors;
// List<> sizes;
// bool feature;
// bool sale;
Posts(this.name, this.picture, this.price, this.id, this.category,this.brand,this.quantity);
}
How could it be solved or is there some way to retrieve a specific child? I know how to show a list but not of a specific child thanks
i fixed it, by some reason the code
postsList.length == 0 ? new Text("No Available"):
was the problem so i deleted it