Reputation: 935
I am trying to get the list to automatically refresh after the delete option on pop up menu is pressed. It will delete the selected item from a list of items called from an api. That item should immediately dissapear after delete is pressed on it.
API call that fills the list with api data:
List data;
@override
void initState() {
super.initState();
this.getJsonData();
}
Future<String> getJsonData() async {
var response = await http.get(
Uri.encodeFull(url),
headers: {"Accept": "application/json"},
);
var extractdata = json.decode(response.body);
data = extractdata['levels'];
levelsData = data;
setState(
() {
var extractdata = json.decode(response.body);
data = extractdata['levels'];
},
);
return "Success";
}
...
Api call that deletes:
delete() async {
String url = "http://31.183.125.253:8080/users";
Map map = {
'price': 1.23,
'user_id': 'user2'
};
print(await apiRequest(url, map));
}
Future<String> apiRequest(String url, Map jsonMap) async {
HttpClient httpClient = new HttpClient();
HttpClientRequest request = await httpClient.deleteUrl(Uri.parse(url));
request.headers.set('content-type', 'application/json');
request.add(utf8.encode(json.encode(jsonMap)));
HttpClientResponse response = await request.close();
String statusCode = response.statusCode.toString();
String reply = await response.transform(utf8.decoder).join();
print(statusCode);
httpClient.close();
return reply;
}
Expansion tile that stores the list from api call:
...
var levelsData = [];
@override
Widget build(BuildContext context) {
List<dynamic> _getChildren() {
List<Widget> children = [];
levelsData.forEach(
(element) {
children.add(
ListTile(
title: Text(element['price'].toString(),
trailing: PopUpMenu(
onDelete: () {
setState(() {
delete();
});
}))
);}
);
return children;
}
}
...
Pop up menu:
class PopUpMenu extends StatelessWidget {
VoidCallback onDelete;
PopUpMenu({this.onDelete});
void showMenuSelection(String value) {
switch (value) {
case 'Delete':
onDelete();
break;
// Other cases for other menu options
}
}
I am able to delete the item selected to delete but the item doesnt dissapear from the list and it didnt show the changes of the list.
Upvotes: 6
Views: 12315
Reputation: 322
I have an issue when deleting items from top and middle of the list view the index isn't in the right range import 'package:flutter/material.dart'; import 'package:flutter_tindercard/flutter_tindercard.dart';
class ExampleHomePage extends StatefulWidget {
@override
_ExampleHomePageState createState() => _ExampleHomePageState();
}
class _ExampleHomePageState extends State<ExampleHomePage>
with TickerProviderStateMixin {
List approved = [];
List refused = [];
List<String> welcomeImages = [
"https://images.unsplash.com/photo-1631636176993-759dea1a1300?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw0fHx8ZW58MHx8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
"https://images.unsplash.com/photo-1631634176568-f543af6a41de?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw3fHx8ZW58MHx8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
"https://images.unsplash.com/photo-1631691971564-adf9419d904e?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxM3x8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
"https://images.unsplash.com/photo-1631641906574-24adb8594649?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxMnx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
"https://images.unsplash.com/photo-1593642702821-c8da6771f0c6?ixid=MnwxMjA3fDF8MHxlZGl0b3JpYWwtZmVlZHwxMXx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
"https://images.unsplash.com/photo-1631621461675-e61a1f28d3d6?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw0NHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60"
];
List<TinderCarder> cards = [];
CardController controller = CardController(); //Use this to trigger swap.
@override
void initState() {
// TODO: implement initState
super.initState();
for (int i = 0; i < welcomeImages.length; i++) {
cards.add(TinderCarder(
controller: controller,
image: welcomeImages[i],
onLeftPress: () {
setState(() {
print('index is: ' + i.toString());
cards.removeAt(i);
print('index is: ' + i.toString());
print('list length: ' + cards.length.toString());
});
},
onRightPress: () {
setState(() {
print('index is: ' + i.toString());
cards.removeAt(i);
print('index is: ' + i.toString());
print('list length: ' + cards.length.toString());
});
}));
}
// cards = welcomeImages.map((element) {
// return TinderCarder(
// image: element,
// controller: controller,
// onLeftPress: () {
// setState(() {
// cards.removeAt(element.indexOf(element));
// print('index is: ' + "${element.indexOf(element)}");
// print('list length: ' + cards.length.toString());
// });
// },
// onRightPress: () {
// setState(() {
// cards.removeAt(element.indexOf(element));
// print('index is: ' + "${element.indexOf(element)}");
// print('list length: ' + cards.length.toString());
// });
// },
// );
// }).toList();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: double.infinity,
child: ListView.builder(
shrinkWrap: true,
key: Key(cards.length.toString()),
physics: ScrollPhysics(),
itemBuilder: (ctx, index) {
return cards[index];
},
itemCount: cards.length,
),
),
);
}
}
class TinderCarder extends StatelessWidget {
final String image;
Function onLeftPress;
Function onRightPress;
var controller;
TinderCarder(
{required this.image,
this.controller,
required this.onLeftPress,
required this.onRightPress});
@override
Widget build(BuildContext context) {
return Container(
height: 300,
child: TinderSwapCard(
orientation: AmassOrientation.BOTTOM,
totalNum: 1,
stackNum: 3,
swipeEdge: 4.0,
maxWidth: double.infinity,
maxHeight: MediaQuery.of(context).size.width * 0.9,
minWidth: MediaQuery.of(context).size.width * 0.8,
minHeight: MediaQuery.of(context).size.width * 0.8,
cardBuilder: (context, index) => Card(
child: Column(
children: [
Image.network(
image,
width: double.infinity,
height: 200,
fit: BoxFit.cover,
),
Text('Data')
],
),
),
cardController: controller,
swipeUpdateCallback: (DragUpdateDetails details, Alignment align) {
/// Get swiping card's alignment
if (align.x < 0) {
} else if (align.x > 0) {}
},
swipeCompleteCallback: (CardSwipeOrientation orientation, int index) {
print(orientation.toString());
if (orientation == CardSwipeOrientation.LEFT) {
print("Card is LEFT swiping");
// print(welcomeImages.length);
onLeftPress();
} else if (orientation == CardSwipeOrientation.RIGHT) {
print("Card is RIGHT swiping");
// print(welcomeImages.length);
onRightPress();
}
},
),
);
}
}
Error
======== Exception caught by animation library ===================================================== The following RangeError was thrown while notifying status listeners for AnimationController: RangeError (index): Invalid value: Not in inclusive range 0..3: 4
Upvotes: 0
Reputation: 52554
You have to call setState and remove the item from your list.
class _MyListViewState extends State<MyListView> {
MyDB _myDB;
List<MyItem> _myList;
...
void getData() async {
...
_myDB.getData().then((items) {
setState(() {
_myList = items;
});
});
}
@override
void initState() {
super.initState();
getData();
}
@override
Widget build(BuildContext context) {
return (_myList== null || _myList.isEmpty)
? Center(child: Text('Nothing to see...'))
: ListView.builder(
itemCount: _myList.length,
itemBuilder: (context, index) {
return
... onPress ...
_myDB.deleteItem(_myList[index]).whenComplete(() {
setState(() {
_myList.removeAt(index);
});
});
Upvotes: 5
Reputation: 480
Flutter should automatically update to reflect changes to datasources. However, this is only applied after calling:
setState((){
});
So that should be run after you delete the item from the list.
Upvotes: 5