Fatih Tirek
Fatih Tirek

Reputation: 48

How to achieve delete and undo operations on Dismissible widget in Flutter?

Questions:

1-) I have a data lists coming from sqlite database and I want to show them in UI. Also when user dismiss a card I want to delete it from database but if user taps undo then I want to bring it back. The problem is when I dismiss a card it's giving error:

A dismissed Dismissible widget is still part of the tree.

I searched solution for this problem but none of them fit my case because I use Bloc for these operations and other solutions were about setState

You can see in here: GIF

2-) Also when I swipe card card's background color clipping: Photo

How to fix these issues?

return Dismissible(
  key: Key(widget.task.id.toString()),
  background: Container(
    decoration: BoxDecoration(
      borderRadius: BorderRadius.circular(8),
      color: Colors.red,
    ),
  ),
  onDismissed: (direction) async {
    Task copied = widget.task;
    taskBloc.deleteTask(widget.task.id);
    changeValue(widget.task.categoryId, false);
    Flushbar(
      messageText: Text('Task deleted', style: bodyText.copyWith(
        color: Colors.white
      )),
      duration: Duration(seconds: 10),
      margin: EdgeInsets.all(8),
      borderRadius: 8,
      icon: Icon(FontAwesomeIcons.infoCircle, color: widget.color),
      flushbarStyle: FlushbarStyle.FLOATING,
      dismissDirection: FlushbarDismissDirection.HORIZONTAL,
      mainButton: FlatButton(
        onPressed: () async {
          taskBloc.addTask(copied);
          changeValue(widget.task.categoryId, true);
        },
        child: Text('Undo', style: bodyText.copyWith(color: widget.color)),
      ),
    )..show(context);
  }),

Upvotes: 2

Views: 3329

Answers (3)

Fiacre AYEDOUN
Fiacre AYEDOUN

Reputation: 81

You just forget to remove element to current list and refresh with setState(() {})

return Dismissible(
  key: Key(widget.task.id.toString()),
  background: Container(
    decoration: BoxDecoration(
      borderRadius: BorderRadius.circular(8),
      color: Colors.red,
    ),
  ),
  onDismissed: (direction) async {
    Task copied = widget.task;
    taskBloc.deleteTask(widget.task.id);
    changeValue(widget.task.categoryId, false);
    setState(() {})
    Flushbar(
      messageText: Text('Task deleted', style: bodyText.copyWith(
        color: Colors.white
      )),
      duration: Duration(seconds: 10),
      margin: EdgeInsets.all(8),
      borderRadius: 8,
      icon: Icon(FontAwesomeIcons.infoCircle, color: widget.color),
      flushbarStyle: FlushbarStyle.FLOATING,
      dismissDirection: FlushbarDismissDirection.HORIZONTAL,
      mainButton: FlatButton(
        onPressed: () async {
           // to success rollback you must change id because of (Key(widget.task.id.toString())),
           // otherwise you will get the same error
          taskBloc.addTask(copied);
          changeValue(widget.task.categoryId, true);
        },
        child: Text('Undo', style: bodyText.copyWith(color: widget.color)),
      ),
    )..show(context);
  }),

Upvotes: 0

Alex Aung
Alex Aung

Reputation: 3159

void _onDismissed(BuildContext context, index) => setState(
    () {
      FavouriteSong favouriteSong = favouriteSongs[index];
      favouriteSongs.removeAt(index);
      BlocProvider.of<FavouriteSongBloc>(context)
          .add(DeleteFavouriteSong(favouriteSong: favouriteSong));

      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content:
              AutoSizeText("${favouriteSong.title} ကိုဖျက်လိုက်ပါပြီ။"),
          duration: const Duration(seconds: 3),
          action: SnackBarAction(
            label: 'မဖျက်တော့ပါ',
            onPressed: () {
              favouriteSongs.insert(index, favouriteSong);

              BlocProvider.of<FavouriteSongBloc>(context).add(
                CreateFavouriteSong(favouriteSong: favouriteSong),
              );
            },
          ),
        ),
      );
    },
  );

Upvotes: 0

Khadga shrestha
Khadga shrestha

Reputation: 1180

You can achieve this passing confirmDismiss in the Dismissible widget as given below which should return either true else false;

 confirmDismiss: (val) async {    
 return await  AlertDialog(
      title: Text('Delete'),
      content: Text('Are you sure to delete?'),
      actions:[
        FlatButton(
          child:Text("Yes"),
          onPressed:()=>Navigator.pop(context,true)
        ),
         FlatButton(
          child:Text("No"),
          onPressed:()=>Navigator.pop(context,false)
        ),
      ],
    )??false;    
 }

After that the onDismissed is called only when the Yes button is clicked . after the dismissed is called remove the item from the current list

Upvotes: 7

Related Questions