Now the next question is how can we do that same thing that we did in our command line when we said
find and we managed to grab hold of all of our documents inside our items collection?
How can we do that inside our app.js
so that we can actually send it over to our list.ejs to render in our ToDo list?
This is what the Mongoose find method looks like.
We specify the model name and then we specify some conditions
and then we get a callback which includes an error and the results from the find
if there were any.
And then we can use the results documents inside that callback.
So as a challenge I want to be able to log all of the items inside our items collection but do that
from our app.
js. Pause the video and try to complete the challenge.
All right.
So we're going to try and find them and then we're going to send them over to our list.ejs.
So I'm going to call that Mongoose method right here inside my root route.
I'm going to tap into the model which represents our collection of items and then I'm going to use that
find method
I spoke about earlier on.
Now in this case the conditions for our find is actually pretty much just find all.
So it's just going to be an empty set of curly braces.
This will find us everything that's inside our items collection.
And then once we found those items then we can trigger the callback which has an error and foundItems
or anything you wish to call it really.
But this is going to contain the things that we found inside the items collection.
Now that we've got that we can log our found items
and now I can get this method to trigger if I just go and access my home page or my root route.
Let's save our app.js,
let's go back into our terminal and I'm going to hit CONTROL + C to end my process and now I'm going
to start it off with nodemon.
This way it will run our app every single time I make some changes in our app.js.
Now on Node server is up and running and if we go over to our localhost:3000 and hit refresh.
So while we're able to log all of our items by using that find function that Mongoose gave us over here,
our website is kind of broken because it doesn't know what this thing items is that we're trying to
pass over to our list
.ejs.
And that's because items no longer exist
right? Items referred to our items array which were deleted and instead we want to pass over the found
Items instead.
So let's go ahead and move our res.render into this callback here and instead of logging the found
Items I'm going to pass over the foundItems to our list.
ejs instead.
So now if we hit save, nodemon should update our server
and if we go ahead and refresh our website then you can see we no longer have any bugs but we still
have some problems tho.
And the first problem is that our items are being rendered in their entirety, like the entire document
is being put into each one of our list items here.
What we want is just the part that comes in the name field right?
Not the whole ID and version and all of the rest of it.
So that's problem number 1.
Now problem number 2 is that every single time that we rerun our app.js with nodemon we insert more
items into our database because it's rerunning this item.
insertMany line of code.
That means if I go over here and I just hit "rs" to restart my server
now if I refresh my localhost:3000 I have even more items which is not what we want at all.
We only want it to have three.
So let's see how we can address these two problems.
Now the first one is slightly easier to address. If we head over to our views and go over to our list
.ejs then you can see that here we're rendering each of the list items just by carrying out a simple
FOR loop.
This is the traditional FOR loop
right?
And we're tapping into this thing called newListItems at the index i.
And each of these items happens to be a document inside our items collection. Instead of adding the entirety
of the documents collection we can simply tap into its name field.
So now when I head back to my todo list and I refresh
we're only putting in the name field of each of the items instead. Now the next thing I want to do is
I want to give you a challenge. Because currently we're using these traditional FOR loop and it's making
it a little bit cluttered and it's a little bit hard to see what's actually going on. As a challenge
I want you to implement the for each method that we get access to in Javascript
ES6 or new versions. Just as a reminder forEach syntax looks something like this.
We tap into a method on an array. Every array in the newer versions of Javascript has access to this
thing called forEach.
And inside the forEach method we get to have a callback function and we get to tap into every single
one of the items inside the array and then we get to use it inside the callback.
Now as a challenge I want you to pause the video and rewrite our simple FOR loop into a forEach loop and
still make it work
when we reload our ToDo list website.
All right so first things first.
I'm going to leave our FOR loop aside and I'm going to rewrite it from scratch.
The thing that we have access to over here is something called newListItems and that corresponds to
all of the found items that we passed over inside our root route.
That means we can tap into this thing called newListItems and we know it's an array of item documents.
So therefore we can call the forEach loop on it. And inside the parentheses we pass in a callback function
which allows us to tap into each item inside that array. And now we open up our callback
and inside these curly braces we can use each of those to item documents. Inside here
I'm going to copy and paste my div and instead of using the new list items at index i .name inside
my paragraph,
I'm just going to tap into that item object that I get access to now and type .name
to access the name property.
And now all I have to do because this is EJS, I'm going to include those little angle brackets and percentage
signs around every single line where I have some code.
So it's the first and the last line basically.
So now I can go ahead and delete what remains of my traditional FOR loop and if I hit save and refresh
we still get exactly the same appearances of our todo list and nothing has broken even though we've
refactored our FOR loop to turn it into a forEach loop.
Now the next problem we're going to tackle is all of these repeated inserts.
The simplest solution which we did previously is we simply commented out this insertMany method after
the first time it's run.
But if you imagine that if our servers hosted somewhere like Heroku or somewhere else, we can't actually
go in there after the first time it's run and then sort of comment out a function right?
It doesn't really work.
So how can we do this in a little bit of a better way?
Well we kind of only want our default items to be inserted if our items collection is actually empty
right?
So we have to somehow check when a user accesses the root route whether if the items collection is empty
in which case we're going to add all of our default items, but otherwise we're not going to add another
set of default items in there. So the first thing we're going to do is we're going to clear out our database
and we can do that
the easiest inside our Mongo shell.
So if we go ahead and see which DB, we're using. We're currently using the todolistDB.
If I write "db.dropDatabase()" then I will execute the command to basically delete my
database.
So now if I write "show dbs" you can see the todolistDB no longer exists.
So we have a blank slate and we're going to recreate it using our app.js.
Now if I comment out this part where we're actually inserting our items into our items collection and I hit save,
then when my app runs you can see I have no items at all. And if I tried to log my found items here then
if I refreshed my homepage to tap into the root route and have a look in my console, then what I get is
just an empty array.
So an array with no items
right?
How can we check for this?
How can we check to see if our collection of items is empty or if the array has no items?
Well, we can simply use an IF statement and check what is the length of this array called foundItems
because if it's equal to zero then that means we have the same condition as we have right now
right?
Just an empty array.
We didn't find any items inside that collection.
Well in that case and only in that case do we actually want to save our default data.
So now I'm going to move this insertMany into here and I'm going to uncomment it to insert our default
items into our database
if there are currently no items in the collection. Else however I'm not going to add anything and I'm
just going to render my list.
ejs. Currently
I have no items inside my items collection.
If I hit save and I go into my browser and I hit refresh, you can see that inside my console it tells
me that I've successfully saved my items to the database.
But on the browser I'm not getting those items show up right?
So how can I get it to do that?
Well, if we take a look at the code when all items collection has no items then we simply just insert
three new items in there.
But then that's kind of the end
right? We don't render anything.
We don't try and render those items that we just added. As a shortcut
what we can do is we can simply call res.redirect and we redirect back onto the root route.
So what this will do is it'll check firstly to see if there are any items in our items collection and
if there are none then it's going to create three items and add it into items collection.
And then finally it's going to redirect back into this root route
but now this time it's not going to fall into the IF block.
Instead it's going to go into the ELSE block because now we actually do have items in our items collection
and were able to res.render those new items over to our list.
ejs.
So let's run that again.
And now you can see if we refresh our website we have all of our default items showing up but no matter
how many times I restart my server I've still only got three items and it doesn't stop building up.