0

I have a list view in my app, I have written some of the code for each item of the list view in the widget containing the list view itself but for the other part I have defined a new child widget. When I try deleting the last element of this list from inside the child widget of the list item, flutter gives me a range error.

RangeError (RangeError (index): Invalid value: Valid value range is empty: 0)

The interesting part is, if I try deleting the item in the list through the code inside the parent widget itself, I don't get an error. This is the parent widget:

class _TodosState extends State<Todos> {

     TodosDB _todosdb = GetIt.I.get();
     List<Todo> _todos = [];
     _loadTodos() async {
       final todos = await _todosdb.getAllTodos();
       setState(() => _todos = todos);
     }
     
    _deleteTodo(int todoId) async {
       await _todosdb.deleteTodo(todoId);
       _loadTodos();
    }
          @override
  Widget build(BuildContext context) {
    double screenWidth = MediaQuery.of(context).size.width;
    double screenHeight = MediaQuery.of(context).size.height;

    return Column(
      children: [
        Container(
          height: screenHeight * 0.6,
          width: screenWidth * 0.9,
          child: ListView.builder(
              itemCount: _todos.length,
              itemBuilder: (BuildContext context, int index) {
                return OpenContainer(
                  useRootNavigator: true,
                  transitionDuration: const Duration(milliseconds: 500),
                  closedBuilder: (context, action) {
                    return Row(
                      children: [
                        Text(_todos.elementAt(index).taskName),
                        IconButton(
                          tooltip: "Delete tag",
                          onPressed: () {
                            //this doesn't give an error
                            _deleteTodo(_todos.elementAt(index).id);
                          },
                          icon: const Icon(
                            Icons.delete,
                            color: Color.fromARGB(255, 99, 99, 99),
                          ),
                        ),
                      ],
                    );
                  },
                  openBuilder: (context, action) {
                    return InputModal(
                      action: action,
                      onDelete: () {
                         // this is throwing the error
                        _deleteTodo(_todos.elementAt(index).id);
                         action.call();
                      },
                      todo: _todos.elementAt(index),
                      time: widget.time,
                      timeType: widget.timeType,
                      index: index,
                    );
                  },
                );
              }),
        ),
      ],
    );
  }
}

This is the child widget:

class _InputModalState extends State<InputModal> {

  @override
  Widget build(BuildContext context) {

    return Container(
      color: const Color(0xffBA99FF),
      padding: const EdgeInsets.fromLTRB(20, 40, 5, 20),
      child: Column(
        children: [
          IconButton(
            onPressed: widget.onDelete,
            tooltip: "Delete this task",
            icon: const Icon(
              Icons.delete,
              size: 30,
            ),
          ),
        ],
      ),
    );
  }
}

I assume that after deleting the item from the child widget, the state of the list which is provided to the list view in the parent widget doesn't get updated. How can I make sure this doesn't happen?

Pro
  • 445
  • 4
  • 14

2 Answers2

0

may be do _deleteTodo(_todos.elementAt(index).id); same in children widget as we have already passed index...

0

The UI is not rebuilding upon deleting an item from the child. Please add a setState callback in your delete method.

    _deleteTodo(int todoId) async {
       await _todosdb.deleteTodo(todoId);
       _loadTodos();
       setState((){});
    }
Usama Karim
  • 1,100
  • 4
  • 15
  • An empty setState callback? – Pro Aug 07 '22 at 06:28
  • setState tells flutter to rebuild the widget. It doesn't matter whether you add some code inside the callback of setState or keep it empty. – Usama Karim Aug 07 '22 at 07:51
  • If you check the implementation of [setState](https://api.flutter.dev/flutter/widgets/State/setState.html) you would know that the callback is doing nothing. But it's recommended by flutter team to add code inside callback to make it **readable**. – Usama Karim Aug 07 '22 at 07:55
  • Nope, doesn't work. Also the _loadTodos method has a setState callback – Pro Aug 07 '22 at 11:35