Skip to main content

Creating multiple lists - Morning Code

 

My goal is to code every morning for 1 hour. In this series, I will share with you what I accomplished during my daily Morning code sessions. 


While this is not a tutorial I'm sure you will find it useful. I am sharing my experience developing my shopping list app. 

 I will share what the app looked like at the beginning and the end of the session. I will share the code snippets that I added and how I troubleshot any issues that came up. 


So I am working on adding a screen to my shopping list app where you can create more than one list. What I want it to display is the box to add a list even when there are no lists in the collection. I am using firebase cloud firestore as a database to hold the lists. But right now all I see is a blank screen. I think that is because I told it that if the database is empty display an empty box.

Screen shot of the blank screen that I see instead of the add list tile.

if (!snapshot.hasData) {
return Container();
}

Ok, I kept getting the following error "Vertical viewport was given unbounded height."  I think that this is what was making the screen go blank. Whenever I would change the Container widget to anything else it would show up for a second then go away. So I googled that error and found a StackOverflow post about it. I learned that the issue is that I am using GridView.count inside the Column Widget. So I need to try wrapping the GridView with an Expanded Widget. 

That was it. That is what the issue was.  The GrideView code now: 

return Expanded(
child: GridView.count(
crossAxisCount: 2,
children: listTiles,
),
);

I also changed the size of the list tile using MediaQuery. So the container that wrapped the Card Widget has a width and height set to:

Container(
width: MediaQuery.of(context).size.width * .30,
height: MediaQuery.of(context).size.height * .25,
child: Card(
color: Colors.orange,
child: Text(
listName,
style: TextStyle(color: Colors.black),
),
),
),



I created an Alert Dialog to pop up when you press the Start a New List tile. 


showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Enter a Name for your new list"),
content: SingleChildScrollView(
child: Column(
children: [
TextField(
onChanged: (value) {
setState(() {
var listTitle = value;
});
},
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
MaterialButton(
onPressed: () {},
child: Text("Add"),
color: Colors.indigo,
textColor: Colors.white,
),
SizedBox(
width: 10,
),
MaterialButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Cancel'),
),
],
),
],
),
),
);
});
},

To create an Alert Dialog you have to wrap it in a Show Dialog widget. Otherwise, it will not show up when you press the button.  In order to have the text field and buttons underneath, I wrapped the text field in a singleScrollChildWidget then gave that a Column as a child. To make the buttons appear side by side I added a row widget within the column widget.  

For the cancel button functionality, I wanted it to just go back to the regular screen so in the On Pressed parameter of the Material Button I used Navigator.Pop(context). This works the same as tapping off the alert dialog. 


Okay so I added the add button functionality to take what was entered into the text field and add that to the database in firebase and I see that it was added into firebase but it is not showing up in the app as a new list tile. 

MaterialButton(
onPressed: () {
FirebaseFirestore.instance
.collection(userIdentification)
.add({
'item': listTitle,
'timeStamp': DateTime.now()

});
},
child:
Text("Add"),
color: Colors.
indigo,
textColor: Colors.
white,
),

So I figured out that the reason why it was not showing up is that my parameters were mismatched. In the StreamBuilder, I had the title variable set to 'listName' but when I sent the data to firebase firestore in the add button of the Alert Dialog it was set to 'item'.

for (var list in lists) {
final title = list.data()['listName'];
final id = list.id;
final lBlock = ListBlock(listName: title, listId: id);
listTiles.add(lBlock);
}
VERSUS
  onPressed: () {
FirebaseFirestore.instance
.collection(userIdentification)
.add({
'item': listTitle,
'timeStamp': DateTime.now()

});

So I changed 'listName' to 'item'. But it still wasn't appearing so I took a look at the part of my code where I tell it to order by the timestamp so that it won't just place the list tiles anywhere but will place them one after another in the order they were created. Again I found that my parameters were mismatched.  In the StreamBuilder, I spelled TimeStamp with a capital 'T' but when I sent the data over to firebase firestore in my alert dialog I used a lowercase 't'. Once I changed the capital 'T' to a lower case 't' in my StreamBuilder, it worked!

StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection(userIdentification)
.orderBy("TimeStamp")
.snapshots(),
VERSUS
onPressed: () {
FirebaseFirestore.instance
.collection(userIdentification)
.add({
'item': listTitle,
'timeStamp': DateTime.now()

});


Also I figured out how to create a custom document name and add to that document in firebase firestore. After .collection(userIdentification) you should put .doc("the name that you want") then .set("the paramenters that you want to fill in the document) ."

TextField(

  onChanged: (value) {
setState(() {
listTitle = value;
});
},
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
MaterialButton(
onPressed: () {
FirebaseFirestore.instance
.collection(userIdentification)
.doc(listTitle)
.set({
'item': listTitle,
'timeStamp': DateTime.now()

});
},
child:
Text("Add"),
color: Colors.
indigo,
textColor: Colors.
white,
),

Comments