Home > Back-end >  The argument type ‘Widget’ can’t be assigned to the parameter type ‘String’?
The argument type ‘Widget’ can’t be assigned to the parameter type ‘String’?

Time:05-21

How do I use my custom widget Notes? I unfortunately can't use the full code in the AddNoteScreen.

I got this error when I changed a few things from the class I'm taking. Below I've pasted the instructors code, with my custom widget included. I'll comment below with the other changes I tried that lead me to this error.

Custom widget down to bare bones:

class Notes extends StatelessWidget {

TextEditingController notesController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: notesController,  
    );
  }
}
class AddNoteScreen extends StatefulWidget {

  User user;
 AddNoteScreen({
     required this.user,
   });

  @override
  State<AddNoteScreen> createState() => _AddNoteScreenState();
  }

class _AddNoteScreenState extends State<AddNoteScreen> {

  TextEditingController titleController = TextEditingController();
  TextEditingController notesController = TextEditingController();
  
  bool loading = false;

    @override
  void initState(){
    super.initState(
  );
  }

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor:Color (0xFF162242),
        elevation: 0,
      ),

      body: GestureDetector(
        onTap: () {
      FocusScope.of(context).unfocus();
      new TextEditingController().clear();
    },
        child: SingleChildScrollView(
          child: Padding(
            padding: EdgeInsets.all(20),
            child: Column(children: [
              
              Text("Title", style: TextStyle(
                color: Colors.white, 
              ), 
              ),
              SizedBox(
                height: 15,
              ),
              Container(
                height: 60,
                color: Colors.white,
                child: TextField(
                  style: TextStyle(
                    color: Color(0xFF192A4F),
                  ),
                  controller: titleController,
                ),
              ),


              Notes(), // My Custom Widget
            
    
              SizedBox(height: 50,),
              loading ? Center (child: CircularProgressIndicator(),) : Container(
                height: 50,
                
                width: MediaQuery.of(context).size.width,
                child: ElevatedButton(
                  
                  onPressed: ()async{
      
                  if (
                    titleController.text == "" || notesController.text == "") // HERE
                    {
                      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("All fields are required")));
      
                    } else {
                      setState(() {
                        loading = true;
                      });
      
                      await FirestoreService().insertNote(titleController.text, notesController.text, widget.user.uid); // HERE
      
                      setState(() {
                        loading = false;
                      });
                      Navigator.pop(context);
                    }
                }, child: Text("Add Note"),  
        ),),
        ]),),
        ),
      ),
      );
       }
      }

^ above I changed notesController.text == "" to Notes == "" and then notesController.text to Notes()

class FirestoreService{

  FirebaseFirestore firestore = FirebaseFirestore.instance;

  Future insertNote(String title, String notes, String userId)async{
    try{
      await firestore.collection('notes').add({
        "title":title,
        "notes":notes,
        "userId": userId
      });
    } catch (e) {}
  }
}

^ above I changed String to Widget for notes

class NoteModel {
  String id;
  String title;
  String notes;
  String userId;

  NoteModel({
    required this.id,
    required this.title,
    required this.notes,
    required this.userId
  });

  factory NoteModel.fromJson(DocumentSnapshot snapshot){
    return NoteModel(
      id: snapshot.id,
      title: snapshot['title'], 
      notes: snapshot['notes'],
      userId: snapshot['userId']
      );  
  }
}

^ above I changed String to Widget for notes

class HomeScreen extends StatefulWidget {

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final user = FirebaseAuth.instance.currentUser!;

FirebaseFirestore firestore = FirebaseFirestore.instance;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Notes'),
        centerTitle: true,
        backgroundColor: Color (0xFF162242),
        actions: [
          TextButton(onPressed: () => FirebaseAuth.instance.signOut(), child: Text("Sign Out", style: TextStyle(color: Colors.white),),),
        ],
      ),
      body: StreamBuilder(
        stream: FirebaseFirestore.instance.collection("notes").where('userId', isEqualTo: user.uid).snapshots(),
        builder: (context, AsyncSnapshot snapshot){
          if (snapshot.hasData){
            if(snapshot.data.docs.length > 0){
              return ListView.builder(
                itemCount: snapshot.data.docs.length,
                itemBuilder: (context,index) {
                  NoteModel note = NoteModel.fromJson(snapshot.data.docs[index]);
                  return Card(
                    margin: EdgeInsets.only(top: 16, left: 10, right: 10, bottom: 16),
                    child: Column(
                        children: [
                          ListTile(
                           title: Center(child: Text(note.title, style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
                           ),
                           ),
                              onTap: () {
                          Navigator.of(context).push(MaterialPageRoute(builder: (context) => EditNoteScreen(),));},
                            ),

                          
                            ListTile(title: Center(child: 
                            Container(
                              height: 300,
                              child: 
                             Text(note.notes),),), // HERE
                            ),


                    ]),
                  );
                }
              );

            }else Center(child: Text("No notes available", style: TextStyle(color: Colors.white),),);

          }
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                CircularProgressIndicator(),
              ],
            ),
          );
        }),

      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.of(context).push(MaterialPageRoute(builder: (context) => AddNoteScreen(user: user)));
        },
        backgroundColor: Color (0xFF162242),
        child: Icon(Icons.add),
      ),
    );
  }
}

^ Text(note.notes) is where I get the error.

debug console

enter image description here

I don't really know what I'm doing but can something like this work ? Totally different answer is okay too!

I'm sorry that's a lot of code. Any help is appreciated. Also link to the class if anyone is interested https://skl.sh/3wxeMVF

CodePudding user response:

Assumptions

Based on the code and comments I guess the actual class NoteModel and Notes are looking something like this:

class NoteModel {
  Notes  notes;
  ... 
}

class Notes extends StatelessWidget { 
  TextEditingController notesController = TextEditingController();
  ...
}

Problem

This explains the error message The argument type ‘Widget’ can’t be assigned to the parameter type ‘String’?:

Text(note.notes) expects note.notes to be a String. Whereas you changed note.notes to be the Widget Notes.

Solution 1

The widget Text() expects Strings, not another Widget. Thus, change notes back to a String:

class NoteModel {
  String notes;
  ... 
}

Build the rest of your code around this NoteModel, do not change it.

Solution 2

If you want to use

class NoteModel {
  Notes notes;
  ... 
}

then the Text widget would be called something like this:

Text(note.notes.notesController.text)

However, this is NOT recommended, as a NoteModel is a data model. And data models should never hold Widgets. A Widget is meant for showing data, not for holding it. A data model and a Widget serve different functions. Keep them separated.

Firebase

Note, that one cannot store whole Widgets (like Notes) in in Firebase but only Strings, Numbers etc.

(Please always post your current code, not code that is indirectly related related to the issue. Otherwise, people will find it very difficult to spot the problem.)

  • Related