Not able to use a List present in another widget

Issue

I am making a List App which a list of items followed by a checkBox .Then there is a floating action button with a plus sign .On click of it u get a bottomSheet .In the bottom sheet you can enter your task to the textField .On clicking on the add button the tasks gets added .
The ui Looks like thisenter image description here

I am not able to access tasks List that is defined in the task_screen.dart from add_taskScreen.dart . I am getting the below error despite importing the required files

error: Undefined name 'tasks'. (undefined_identifier at [todoey_flutter] lib\add_task_screen.dart:43)

here is my Code

Main.dart

import 'package:flutter/material.dart';
import 'tasks_screen.dart';
void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return  const MaterialApp(
      home: TaskScreen(),
    );
  }
}

Task_tile.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class TaskTile extends StatelessWidget {
  @override
 late final  bool isChecked ;
  late final String taskTitle;
  final Function checkBoxCallBack;
  TaskTile({required this.isChecked,required this.taskTitle,required this.checkBoxCallBack});
  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(taskTitle,
      style:TextStyle(
        decoration:  isChecked ? TextDecoration.lineThrough:null
      ),
      ),
      trailing:  Checkbox(
      value:isChecked,
    activeColor:Colors.lightBlueAccent,
    onChanged: (newValue) {//onChanged here if we select the check box the value becomes true else it will become false
      checkBoxCallBack(newValue);//widget.toggleCheckBoxState(value);
    },
      )
    );
  }
}

Task_list.dart

     import 'package:flutter/material.dart';
import 'task_title.dart';
import 'Models/task.dart';
class TaskList extends StatefulWidget {

  final List<Task> tasks;
  TaskList(this.tasks);

  @override
  State<TaskList> createState() => _TitleListState();
}

class _TitleListState extends State<TaskList> {



  @override
  Widget build(BuildContext context) {
    return ListView.builder(itemBuilder: (context,index){//in the listView Builder index is already defined and gets updated by itself
    return TaskTile(
      taskTitle:widget.tasks[index].name,
      isChecked: widget.tasks[index].isDone,
      checkBoxCallBack:(bool checkBoxState){
        setState((){
          widget.tasks[index].toggleDone() ;
        });
      }
    );
    },
    itemCount: widget.tasks.length,//max no tasks that can fit in the screen ie..how many ever tasks are there on 'tasks' it will build that many
    );
  }
}
    

task.dart

import 'package:flutter/material.dart';
class Task{
  late final String name;
  late bool isDone;

  Task
      ({required this.name,this.isDone=false});//give a default value to isDone

  void toggleDone()
 {
  isDone = !isDone;
 }
}

task_Screen.dart

import 'package:flutter/material.dart';
import 'tasks_list.dart';
import 'add_task_screen.dart';
import 'package:todoey_flutter/Models/task.dart';
class TaskScreen extends StatefulWidget {
  const TaskScreen({Key? key}) : super(key: key);

  @override
  State<TaskScreen> createState() => _TaskScreenState();
}

    class _TaskScreenState extends State<TaskScreen> {
      List<Task> tasks = [
        Task(name: 'Buy milk'),
        Task(name: 'Buy eggs'),
        Task(name: 'Buy bread'),
      ];
      @override
      Widget build(BuildContext context) {
        return  Scaffold(//Scaffold contains everything
          backgroundColor: Colors.lightBlueAccent,
          body:Column(
            children: [
              Container(
                padding:const EdgeInsets.only(top:60,left:30,right:30,bottom: 30),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                    children:const <Widget>[
                       CircleAvatar(
                         child: Icon(
                           Icons.list,
                         color: Colors.lightBlueAccent,
                         size:30.0,
                       ),
                       backgroundColor:Colors.white,
                         radius:30,
                       ),
                     SizedBox(height:10),
                     Text(
                       'Todoey',
                     style:TextStyle(
                       color:Colors.white,
                       fontSize: 50,
                       fontWeight: FontWeight.w700,
                     )
                     ),
                      Text('12 Tasks',
                      style:TextStyle(
                        color:Colors.white,
                        fontSize: 18,
                      )
                      ),
    
                   ]
                ),
              ),
              Expanded(
                child: Container(//designing the white part of the todoey
                  padding:const EdgeInsets.symmetric(horizontal: 20),
                  height:300,
                  decoration: const BoxDecoration(
                      color:Colors.white,
                      borderRadius: BorderRadius.only(
                        topLeft:Radius.circular(20.0),
                        topRight:Radius.circular(20.0),
                      ),
                  ),
                  child: TaskList(tasks),
        ),
                ),
            ],
          ),
          floatingActionButton: FloatingActionButton(
           backgroundColor:Colors.lightBlueAccent,
            child: const Icon(
              Icons.add,
            ),
            onPressed: (){ //call the bottomSheet in builder
             showModalBottomSheet(builder:(context)=>AddTaskScreen(
                     (newTaskTitle)
                 {
               setState(){
                 tasks.add(Task(name:newTaskTitle));
               }
             }), context: context);//to create bottom drawer widget on pressing the button a new pop up appears at the bottom
            },
          ),
        );
      }
    }

add_Task_Screen.dart

import 'package:flutter/material.dart';
import 'task_title.dart';
import 'tasks_list.dart';
import 'tasks_screen.dart';
import 'package:todoey_flutter/Models/task.dart';
class AddTaskScreen extends StatelessWidget {
  late String newTaskTitle;
  final Function addTaskCallBack;
  AddTaskScreen( this.addTaskCallBack, {Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(20.0),
      child: Container(
      //color:const Color(0xff757575),//you cant add color 2 times it will throw an exception
          decoration:const BoxDecoration(
          color:  Colors.white,
          borderRadius: BorderRadius.only(topLeft:Radius.circular(20.0) ,topRight:Radius.circular(20.0)),
        ),
        child:Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children:[
            const Center(
              child: Text('Add Task',
              style: TextStyle(
                fontSize:30.0,
                color:Colors.lightBlueAccent,
              ),
              ),
            ),
             TextField(
              autofocus: true,
                autocorrect: true,
              textAlign: TextAlign.center,
              onChanged: (newText){
               newTaskTitle = newText;
              },
            ),
            FlatButton(
              onPressed: (){

                print(newTaskTitle);
                tasks.add(name:newTaskTitle);//here is the error 
              },
              child: const Text('Add'),
              color: Colors.lightBlueAccent,
            )
          ]
        )
      ),
    );
  }
}

Solution

In task_screen.dart create a function like this

void _handleAddTask(String _name)=>setState(()=>tasks.add(Task(name: _name))));

Then modify showModalBottomSheet to look like this

showModalBottomSheet(builder:(context)=>AddTaskScreen(_handleAddTask,"Add task"), context: context);},),);}}

In add_Task_Screen.dart, modify
AddTaskScreen( this.addTaskCallBack, {Key? key}) : super(key: key); to this

AddTaskScreen( this.addTaskCallBack, this.newTaskTitle, {Key? key}) : super(key: key);

create a TextEditingController for your TextField and pass it to it like this

TextField(
              autofocus: true,
controller: _textFieldController,
                autocorrect: true,
              textAlign: TextAlign.center,
              onChanged: (newText){
               newTaskTitle = newText;
              },
            ),

Finally, in the onPress of Add button, modify it to something like this:

            FlatButton(
              onPressed: (){

                print(newTaskTitle);
addTaskCallBack(_textFieldController.text);
              },
              child: const Text('Add'),
              color: Colors.lightBlueAccent,
            )

Answered By – Eric Aig

Answer Checked By – Pedro (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.