skip to Main Content

I am new to flutter. I am building todo list app by following one of the article. I have managed to find couple of errors already such as asyn and .then method, FieldButton to Text button. I am struggling to fix couple of errors

This is the first error message:

lib/main.dart:88:24: Error: Undefined name '_todoList'.
      for (String title in _todoList) {

This is the second error message:

lib/main.dart:89:22: Error: Method not found: '_buildTodoItem'.
        _todoWidgets.add(_buildTodoItem(title));
                         ^^^^^^^^^^^^^^

Here is my full code:

import 'package:flutter/material.dart';

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

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(title: 'To-Do-List', home: TodoList());
  }
}

class TodoList extends StatefulWidget {
  @override
  _TodoListState createState() => _TodoListState();
}

class _TodoListState extends State<TodoList> {
  final List<String> _todoList = <String>[];
  final TextEditingController _textFieldController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('To-Do List'),
      ),
      body: ListView(children: _getItems()),
      floatingActionButton: FloatingActionButton(
        onPressed: () => _displayDialog(context),
        tooltip: 'Add Item',
        child: Icon(Icons.add),
      ),
    );
  }

  void _addTodoItem(String title) {
    //Wrapping it inside a set state will notify
    // the app that the state has changed

    setState(() {
      _todoList.add(title);
    });
    _textFieldController.clear();
  }

  //Generate list of item widgets
  Widget _buildTodoItem(String title) {
    return ListTile(
      title: Text(title),
    );
  }

  //Generate a single item widget
  Future<AlertDialog> _displayDialog(BuildContext context) async {
    return showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: const Text('Add a task to your List'),
            content: TextField(
              controller: _textFieldController,
              decoration: const InputDecoration(hintText: 'Enter task here'),
            ),
            actions: <Widget>[
              TextButton(
                child: const Text('ADD'),
                onPressed: () {
                  Navigator.of(context).pop();
                  _addTodoItem(_textFieldController.text);
                },
              ),
              TextButton(
                child: const Text('CANCEL'),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              )
            ],
          );
        }).then((showDialog) => showDialog ?? false);
  }
}

List<Widget> _getItems() {
  final List<Widget> _todoWidgets = <Widget>[];
  for (String title in _todoList) {
    _todoWidgets.add(_buildTodoItem(title));
  }

  return _todoWidgets;
}

I have already fixed .then method along with Textbutton. I want to understand how exactly I can find be able to resolve this issue. It’s quite confusing to beging with.

2

Answers


  1. Your definition of the function _getItems() falls outside the class definition, i.e. after the closing bracket }. But _todoList is a property of the class _TodoListState.
    So your function tries to access something that it doesn’t have access to.

    You should include the function _getItems() in your class like this.

    class _TodoListState extends State<TodoList> {
      
      // ... lots of code here...
    
      List<Widget> _getItems() {
        final List<Widget> _todoWidgets = <Widget>[];
        for (String title in _todoList) {
          _todoWidgets.add(_buildTodoItem(title));
        }
        return _todoWidgets;
      } 
    
    }
    

    Do you notice the difference?

    The closing bracket of the class is now placed behind the closing bracket of the function.

    Login or Signup to reply.
  2. in the Dart language, the private members of a class are those with an underscore upfront their name definition, in your case, the _buildTodoItem() method is private and can’t be used anywhere outside its class. in addition, if you want a member from outside, you will need to make an instance of that class and access it.

    This function:

     List<Widget> _getItems() {
      final List<Widget> _todoWidgets = <Widget>[];
      for (String title in _todoList) {
        _todoWidgets.add(_buildTodoItem(title));
      }
      return _todoWidgets;
    }
    

    is outside the State class where the _buildTodoItem method belongs, so the error is thrown.

    you should get back that function inside the State class to fix the error like this:

      class _TodoListState extends State<TodoList> {
      final List<String> _todoList = <String>[];
      final TextEditingController _textFieldController = TextEditingController();
    
    
             
       List<Widget> _getItems() {
      final List<Widget> _todoWidgets = <Widget>[];
      for (String title in _todoList) {
        _todoWidgets.add(_buildTodoItem(title));
      }
    
      return _todoWidgets;
    }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('To-Do List'),
          ),
          body: ListView(children: _getItems()),
          floatingActionButton: FloatingActionButton(
            onPressed: () => _displayDialog(context),
            tooltip: 'Add Item',
            child: Icon(Icons.add),
          ),
        );
      }
    
      void _addTodoItem(String title) {
        //Wrapping it inside a set state will notify
        // the app that the state has changed
    
        setState(() {
          _todoList.add(title);
        });
        _textFieldController.clear();
      }
    
      //Generate list of item widgets
      Widget _buildTodoItem(String title) {
        return ListTile(
          title: Text(title),
        );
      }
    
      //Generate a single item widget
      Future<AlertDialog> _displayDialog(BuildContext context) async {
        return showDialog(
            context: context,
            builder: (BuildContext context) {
              return AlertDialog(
                title: const Text('Add a task to your List'),
                content: TextField(
                  controller: _textFieldController,
                  decoration: const InputDecoration(hintText: 'Enter task here'),
                ),
                actions: <Widget>[
                  TextButton(
                    child: const Text('ADD'),
                    onPressed: () {
                      Navigator.of(context).pop();
                      _addTodoItem(_textFieldController.text);
                    },
                  ),
                  TextButton(
                    child: const Text('CANCEL'),
                    onPressed: () {
                      Navigator.of(context).pop();
                    },
                  )
                ],
              );
            }).then((showDialog) => showDialog ?? false);
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search