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