Home > database >  Error: Undefined name and Method not defined
Error: Undefined name and Method not defined

Time:12-04

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.

CodePudding user response:

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.

CodePudding user response:

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);
  }
}
  • Related