I am getting very stange issue while using listview that having stateful items. i also explain one example here.
the example is about cart screen and every cart item has one button to remove the cart item.
The issue is that- i have one Listview.builder(), and in it's itemBuilder - every item is another Stateful Widget, i am passing one function parameter to that widget and that widget has one IconButton and pressing on that i am calling that parameter function. and inside that function i am removing that item from the list. the item is deleted successfully from list but somehow the state is not deleting.
my code is below
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> list = [
"Item 1",
"Item 2",
"Item 3",
"Item 4",
"Item 5",
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("My Cart"),
),
body: ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) {
return CartComponent(
value: list[index],
onDelete: () {
setState(() {
list.removeAt(index);
});
},
);
},
),
);
}
}
class CartComponent extends StatefulWidget {
final String value;
final Function onDelete;
const CartComponent({Key? key, required this.value, required this.onDelete})
: super(key: key);
@override
State<CartComponent> createState() => _CartComponentState();
}
class _CartComponentState extends State<CartComponent> {
String? name;
@override
void initState() {
super.initState();
name = widget.value;
}
@override
Widget build(BuildContext context) {
return Card(
margin: const EdgeInsets.all(10),
child: SizedBox(
height: 80,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Text(
"$name",
style: const TextStyle(fontSize: 16),
),
),
IconButton(
onPressed: () {
widget.onDelete();
},
icon: const Icon(Icons.clear),
),
],
),
),
);
}
}
the item is removed from the list successfully, and list length is also decreasing but from the view aspect, the last element of the list is being removed (but practically from the List, last item is not removing)
CodePudding user response:
Try this, in your CartComponent add this:
final Function(String) onDelete;
and in press button:
onPressed: () {
widget.onDelete(widget.value);
},
and in ListView builder do this:
ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) {
return CartComponent(
key: UniqueKey(), // the very important part
value: list[index],
onDelete: (value) {
setState(() {
list.remove(value);
});
},
);
},
)
CodePudding user response:
You can directly use widget.value
on text Text(widget.value,
this will work.
You can change delete function like
or
final Function(String value) onDelete;
And pass value widget.onDelete(name!);
Now on itemBuilder
return CartComponent(
key: ValueKey("item ${list[index]}"),
value: list[index],
onDelete: (v) {
list.remove(v);
print(v);
setState(() {});
},
);
},
For now,
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> list = [
"Item 1",
"Item 1",
"Item 2",
"Item 3",
"Item 3",
"Item 4",
"Item 5",
"Item 5",
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) {
return CartComponent(
key: ValueKey("item ${list[index]}"),
value: list[index],
onDelete: () {
list.removeAt(index);
setState(() {});
},
);
},
),
);
}
}
class CartComponent extends StatefulWidget {
final String value;
final Function onDelete;
const CartComponent({
Key? key,
required this.value,
required this.onDelete,
}) : super(key: key);
@override
State<CartComponent> createState() => _CartComponentState();
}
class _CartComponentState extends State<CartComponent> {
String? value;
@override
void initState() {
super.initState();
value = widget.value;
}
@override
Widget build(BuildContext context) {
return Card(
margin: const EdgeInsets.all(10),
child: SizedBox(
height: 80,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Text(
value!,
style: const TextStyle(fontSize: 16),
),
),
IconButton(
onPressed: () => widget.onDelete(),
icon: const Icon(Icons.clear),
),
],
),
),
);
}
}