flutter SingleChildScrollView remove item

603

Removing the offer from within itself is not the best practice but you can accomplish it in a number of ways. The first I can think of is to pass a function that removes it when creating the offer like this:

items.add(offer(name, category, context,..., () {
   setState(() {
      FirebaseFirestore.instance
                      .collection('Offers')
                      .doc(element['id'])
                      .delete();
      items.remoev(index);
   });
}));

You'll need to create the index beforehand and increase it each time but I don't recommend doing it. The way I would done do this is change the offer to be:

dynamic offer(name, category, context,) {

  return Container(
        child: Row(
           children: [
              Text(name),
              Text(category),
          ],
        ),
      );
}

And when creating the offer wrap it in the GestureDetector like this:

items.add(GestureDetector(
             child: offer(name, category, context,...)),
             onTap: () {
                setState(() {
                    FirebaseFirestore.instance
                      .collection('Offers')
                      .doc(element['id'])
                      .delete();
                    items.remoev(index);
                });
             },
         );

You'll have to do the same thing with the index but I consider it a better approach since the child has no power over the parent and can't change its state which is a good practice.

Share:
603
user1209304
Author by

user1209304

Day job GitHub account: https://github.com/adsklowenthal

Updated on December 29, 2022

Comments

  • user1209304
    user1209304 about 1 year

    I have the following code where I generate a list of items(data is taken from Firebase). I would like to implement a functionality to remove items but I don't know how to access the list and how to remove items:

    class _MyOfferState extends State<MyOffer> {
      List<Widget> items = [];
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
    ...
              body: SingleChildScrollView(
                child: Column(
                  children: [
                    StreamBuilder<QuerySnapshot>(
                      stream: FirebaseFirestore.instance
                          .collection('Offers')
                      builder: (BuildContext context, snapshot) {
                          snapshot.data.docs.forEach((element) {
                            element.get('items').forEach((item) {
                              String _name = element['name'];
                              String _category = item['category'];
    
                              items.add(offer(name, category, context,...));
    
                            });
                }
                          );
                        }
                        return new Column(
                          children: List.unmodifiable(() sync* {
                            yield* items;
                          }()),
                        );
                      },
              ),
            
      }
    }
    

    This is a dynamic class where I have GestureDetector. The item should be deleted when a user clicks on the it.

    dynamic offer(name, category, context,) {
    
      return GestureDetector(
          child: Container(
            child: Row(
                        children: [
                          Text(name),
                          Text(category),
              ],
            ),
          ),
        ),
        onTap: () {
          
     // remove item should be here
        },
      );
    }
    
    • James 666
      James 666 almost 3 years
      Have you managed to display the data in a listview? If not, try creating a listview.builder flutter.dev/docs/cookbook/lists/long-lists
    • James 666
      James 666 almost 3 years
      If you want to remove a specific item from a list, you call items.removeAt(index). Let us know if you need it to be more specific than this - what exactly are you trying to remove from your list?
    • user1209304
      user1209304 almost 3 years
      From the class dynamic offer I need somehow identify which item in the list was clicked, then remove this item from the list and then rebuild SingleChildScrollView
    • James 666
      James 666 almost 3 years
      Ok, use a listview.builder to display the list of your items and in the itemBuilder argument you can find the item which was clicked through: (context, index){ return GestureDetector(child: Container(), onTap: (){ print(items[index]) } ) }
    • James 666
      James 666 almost 3 years
      Just to note, don't ever rebuild an entire SingleChildScrollView with all of its widgets inside it - in Flutter you only need to rebuild widgets that have state changes. If you rebuild an entire SingleChildScrollView, you will get jank and it will create a very bad UX
    • yellowgray
      yellowgray almost 3 years
      From your original structure, you want to delete the data on FirebaseFirestore, right? The Stream already listens to any change on Firestore and rebuilds itself.
    • user1209304
      user1209304 almost 3 years
      I want to delete data from FirebaseFirestore and rebuild UI to display the correct list of items.
    • CoderUni
      CoderUni almost 3 years
      I think what you're looking for is two SliverList inside a CustomScrollView so that you can have two different lists that scroll together. The first one would need to be a SliverList with a builder delegate. youtube.com/watch?v=ORiTTaVY6mM
  • user1209304
    user1209304 almost 3 years
    Thanks for the answer. But I don't know how to call a setState from class "offer". I'm getting error: setState() called in constructor: _MyOfferState#1489b(lifecycle state: created, no widget, not mounted)
  • Jim
    Jim almost 3 years
    why dont you make dynamic as a Widget in class _MyOfferState, updated
  • user1209304
    user1209304 almost 3 years
    If I'm doing as you suggested then instead of removing elements I see additional elements on the screen. Looks like it does not remove elements from the List but makes some copy.