0

In the code below I am trying to build a basic ToDo list app using flutter. I have a FAB and when it is pressed, it asks the user to enter a text in the popped up alert dialog that contains a TextField. I also use a TextEditingController to get the text and add it to a list of strings. I have a counter variable to keep track of items being added to the list and to use it as index of the list when I want to show the item from the list and add it to the ListView as a ListTile.

When I run the code it says the index is out of range and I really don't know what else should I take care of. Sorry if my question is basic, I am newbie.

My Code:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ToDo List',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyTaskList(),
    );
  }
}

class MyTaskList extends StatefulWidget {

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

class _MyTaskListState extends State<MyTaskList> {
  final _taskItems = <String>[];
  var _counter = 0;
  final myController = TextEditingController();


  @override
  void dispose(){
    myController.dispose();
    super.dispose();
  }

  void _addTask(String task){
    setState(() {
      _taskItems.add(task);
    });
    myController.clear();
  }


  Widget _buildTaskList() {
    return new ListView.builder(
        itemCount: _taskItems.length,
        itemBuilder: (BuildContext context, _) {
          print(_taskItems);
          return _buildTask(_taskItems[_counter]);

        }

    );

  }

  Widget _buildTask(String task) {

    return new ListTile(
      title: new Text(task),
    );
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(

        appBar: AppBar(

          title: Text("ToDo List"),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () => showDialog<String>(
            context: context,
            builder: (context) => AlertDialog(
              title: Text("New Task"),
              content: TextField(
                controller: myController,
                decoration: InputDecoration(
                  border: OutlineInputBorder(),
                  hintText: "Enter New Task",
                ),
              ),

              actions: <Widget>[
                TextButton(
                    onPressed: () => {
                      _addTask(myController.text),
                      Navigator.pop(context, "ok"),
                      _counter++,
                      print(_counter),
                      print(_taskItems),


                    },
                    child: const Text("OK")),

              ],
            )
          ),
          child: Center(child:Icon(Icons.add)),

        ),
        body: _buildTaskList(),
    );
  }
}
3
  • 1
    You really had me confused with () => {}, use () {} not () => {} the second is just returning a Set while the first one is void callback. I had to ask on discord. Thank you Miyoyo Commented May 23, 2021 at 12:53
  • @moneeralhashim Thanks for your information but I there's something. If we assume based on what you say then why that piece of my code works even if it is a set being returned?
    – Ethan
    Commented May 23, 2021 at 14:09
  • You really shouldn't use it even though it works. When you write () => {} you are returning a Set literal. It's the same as if you did this () => [] The function part is just () => the [] part is a list being returned while you are making it you can call a function like () => [print('not ok')] but as you can see there's no need to do that here as you can just write () => print('ok') or () {} for grouping expressions. Don't confuse javascript and dart, but even in javascript it introduces ambiguity because it looks like an object and a function body. Commented May 24, 2021 at 9:46

1 Answer 1

1

Edit as below. You can use the ListViewBuilder index, why do you use counter? I think, your initial counter value is 0 but the list is empty. You try to get element 0 (or first)` of empty list, but there is no element.

Widget _buildTaskList() {
    return new ListView.builder(
        itemCount: _taskItems.length,
        itemBuilder: (BuildContext context, index) {
          print(_taskItems);
          return _buildTask(_taskItems[index]);

        }

    );

  }
1
  • Thanks for your answer Reza! Works nice and neat.
    – Ethan
    Commented May 23, 2021 at 14:10

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.