Search code examples
flutterflutter-web

Delete a row by pressing the button


what I wanted to do was that a button would appear in the last cell of the DataTable row and when the user clicked that same row would have to be removed. I couldn't find anything that could help me.

import 'package:app/views/login_page.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';

class ListPage extends StatefulWidget {
  const ListPage({Key? key}) : super(key: key);

  @override
  _ListPageState createState() => _ListPageState();
}

Future<List> getBookings() async {
  var ref =
      FirebaseDatabase.instance.ref("server/bookings/" + currentCard + "/");
  DataSnapshot event = await ref.get();

  List<DataRow> bookings = [];
  for (var meal in event.children) {
    bookings.add(
      DataRow(
        cells: [
          DataCell(Text(meal.child("data").value.toString())),
          DataCell(Text(meal.child("tipo").value.toString())),
          DataCell(Text(meal.child("local").value.toString())),
          DataCell(IconButton(
            icon: Icon(Icons.delete),
            onPressed: () {
              //Delete row
            },
          )),
        ],
      ),
    );
  }

  print(bookings);
  return bookings;
}

class _ListPageState extends State<ListPage> {
  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.center,
      children: [
        Center(
          child: FutureBuilder(
            future: getBookings(),
            builder: (context, snapshot) {
              return DataTable(
                  showCheckboxColumn: true,
                  columns: const [
                    DataColumn(label: Text("Data")),
                    DataColumn(label: Text("Tipo")),
                    DataColumn(label: Text("Local")),
                    DataColumn(label: Text("")),
                  ],
                  rows: snapshot.data as List<DataRow>);
            },
          ),
        ),
      ],
    );
  }
}

The biggest difficulty for me is to get the index of the clicked line to be able to delete it


Solution

  • The main issue with your approach is accessing and changing the data you get with your future.

    This code shows the problem in an minimal example:

    class ExampleWidget extends StatefulWidget {
      ExampleWidget({Key? key}) : super(key: key);
    
      @override
      State<ExampleWidget> createState() => _ExampleWidgetState();
    
      Future<List<Text>> getData() async {
        return [Text('1'), Text('2')];
      }
    }
    
    class _ExampleWidgetState extends State<ExampleWidget> {
      @override
      Widget build(BuildContext context) {
        return FutureBuilder<List<Text>>(
            future: widget.getData(),
            builder: (context, snapshot) {
              if (!snapshot.hasData) return Container();
              return Column(children: snapshot.data!);
            });
      }
    }
    

    As you can see there is no way to edit the list afterwards. To make it accessible, it needs to be added to a state of a widget. The simplest approach here would be just to save your response as a field in your state and build the widgets in the "build" method of your state. Here an example:

    class ExampleWidget2 extends StatefulWidget {
      ExampleWidget2({Key? key}) : super(key: key);
    
      @override
      State<ExampleWidget2> createState() => _ExampleWidgetState2();
    }
    
    class _ExampleWidgetState2 extends State<ExampleWidget2> {
      List<String>? _data;
    
      @override
      void initState() {
        super.initState();
        getData();
      }
    
      Future getData() async {
        _data = ['1', '2'];
      }
    
      @override
      Widget build(BuildContext context) {
        if (_data == null) {
          return Container();
        } else {
          List<Widget> widgets = [];
    
          for (String item in _data!) {
            widgets.add(ElevatedButton(
                 onPressed: () {
                  setState(() {
                    _data!.remove(item);
                  });
                },
                child: Text(item)));
          }
    
          return Column(children: widgets);
        }
      }
    }
    

    As you can see, I added buttons in the second example that remove rows on click by manipulating the state variable and setting the state.