Reputation: 31
Good evening, As in my example image, below, I want to increase or decrease the quantity on button click for a single item in the listing. If I increment the counter in setState(), it is incremented in each element of the list. From what I understand you need to find the index, but it doesn't work (I tried different solutions where there is onPressed)
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:db_local/db.dart';
import 'package:db_local/edit_student.dart';
class ListStudents extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _ListStudents();
}
}
class _ListStudents extends State<ListStudents> {
int _itemCount = 0;
List<Map> slist = [];
MyDb mydb = MyDb();
@override
void initState() {
mydb.open();
getdata();
super.initState();
}
getdata() {
Future.delayed(const Duration(milliseconds: 500), () async {
slist = await mydb.db.rawQuery('SELECT * FROM students');
setState(() {});
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("List of Students"),
),
body: SingleChildScrollView(
child: Container(
child: slist.isEmpty
? const Text("No any students to show.")
: Column(
children: slist.map((stuone) {
ListView.builder(
itemCount: slist.length,
itemBuilder: (context, index) {
List<int> itemCounts =
List.generate(slist.length, (_) => 0);
return Card(
child: ListTile(
leading: const Icon(Icons.people),
title: Text(stuone["name"] + " " + stuone["ID"]),
subtitle: Text("Numero Carte:" +
stuone["roll_no"].toString() +
", Add: " +
stuone["address"]),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(
icon: const Icon(Icons.remove),
onPressed: () =>
setState(() => itemCounts[index]--),
),
Text('$itemCounts'),
IconButton(
icon: const Icon(Icons.add),
onPressed: () =>
setState(() => itemCounts[index]++),
),
],
),
));
},
);
}).toList(),
),
),
),
);
}
}
Update Code
class ListStudents extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _ListStudents();
}
}
class _ListStudents extends State<ListStudents> {
//int _counts = 0;
List<int> _itemCounts;
List<Map> slist = [];
MyDb mydb = MyDb();
//_ListStudents(this._itemCounts);
@override
void initState() {
mydb.open();
getdata();
super.initState();
}
getdata() {
Future.delayed(const Duration(milliseconds: 500), () async {
slist = await mydb.db.rawQuery('SELECT * FROM students');
_itemCounts = List.generate(slist.length, (_) => 0);
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("List of Students"),
),
body: slist.isEmpty
? Text('No any students to show.')
: ListView.builder(
itemCount: slist.length,
itemBuilder: (context, index) {
final stuone = slist[index];
return Card(
child: ListTile(
leading: const Icon(Icons.people),
title: Text(stuone["name"] + " " + stuone["ID"]),
subtitle: Text("Numero Carte:" +
stuone["roll_no"].toString() +
", Add: " +
stuone["address"]),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(
icon: const Icon(Icons.remove),
onPressed: () => setState(() => _itemCounts[index]--),
),
Text(_itemCounts[index].toString()),
IconButton(
icon: const Icon(Icons.add),
onPressed: () => setState(() => _itemCounts[index]++),
),
],
),
),
);
},
),
);
}
}
Upvotes: 0
Views: 1160
Reputation: 8607
Instead of slist.map((stuone) {...}
you could use the ListView.builder()
instead which gives you the index for each element that will be displayed.
So something like this:
ListView.builder(
itemCount: slist.length,
itemBuilder: (context, index) {
return Card(
child: ListTile( ... )
),
},
)
There are different options for storing the state. But without to much intervention you could instead of int _itemCount = 0
have a List<int> itemCounts = List.generate(slist.length, (_) => 0);
which you set after you've fetched the data and assign to a state variable.
You can then for each button, increment or decrement the value e.g. as: itemCounts[index]++;
Update to clarify:
Obviously not tested, but this should give you directions for how to construct the code and use the widgets. You shouldn't use the ListView as you did within a column within a scrollview.
// under class _ListStudents extends State<ListStudents> {
late final List<int> _itemCounts;
// assign _itemCounts in getData()
getdata() {
Future.delayed(const Duration(milliseconds: 500), () async {
slist = await mydb.db.rawQuery('SELECT * FROM students');
_itemCounts = List.generate(slist.length, (_) => 0);
setState(() {});
});
}
// When building your scaffold:
body: slist.isEmpty ?
Text('No any students to show.') :
ListView.builder(
itemCount: slist.length,
itemBuilder: (context, index) {
final stuone = slist[index];
return Card(
....
);
}
)
Upvotes: 2