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?


Solution 1: Janam Maharjan

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


Solution 2: Usama Karim

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((){});
    }