Full Stack Web Development for Beginners- Part 4: Final Project, Node, Express & MongoDB | Chris Dixon | Skillshare

Playback Speed

  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Full Stack Web Development for Beginners- Part 4: Final Project, Node, Express & MongoDB

teacher avatar Chris Dixon, Web Developer & Online Teacher

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

66 Lessons (10h 7m)
    • 1. Welcome to the course!

    • 2. What we will be building

    • 3. What is Node & NPM?

    • 4. Static v dynamic web server

    • 5. Express.js and express generator

    • 6. Express project structure

    • 7. Using Nodemon

    • 8. Serving static files

    • 9. Introduction to Pug

    • 10. Template inheritance

    • 11. Time to practice: Creating the header

    • 12. Solution: Creating the header

    • 13. Mixins

    • 14. Basic routing

    • 15. Route parameters

    • 16. MVC Pattern

    • 17. Using controllers

    • 18. Using middleware

    • 19. Important Update: mLab now part of Mongo

    • 20. Getting started with Mongo

    • 21. Mongoose models

    • 22. Creating our hotel upload form

    • 23. Pushing to the database

    • 24. Querying the database

    • 25. Distinct values

    • 26. The aggregation pipeline

    • 27. The edit and remove form

    • 28. Updating records

    • 29. Deleting records

    • 30. Hotel detail view

    • 31. Locals and conditional rendering

    • 32. Hotels by country

    • 33. Styling the header- small screen

    • 34. Styling the content- small screen

    • 35. Large screen styling

    • 36. Countries mixin

    • 37. Promise.all and array destructuring

    • 38. Environment variables

    • 39. Handling file uploads

    • 40. Saving images to the cloud

    • 41. Retrieving images from the cloud

    • 42. Hotel search form part 1

    • 43. Hotel search form part 2

    • 44. Search results template

    • 45. Hotel detail search from

    • 46. Creating the user model

    • 47. Sign Up Form

    • 48. Validating User Input

    • 49. Passing errors to the template and sanitization

    • 50. Registering new users

    • 51. Password encryption

    • 52. Logging in

    • 53. Logging out

    • 54. Working with sessions

    • 55. Providing user feedback with flash messages

    • 56. User conditional rendering

    • 57. The order model

    • 58. Booking confirmation page

    • 59. Placing orders

    • 60. User account area

    • 61. Displaying all orders

    • 62. Final CSS

    • 63. Preparing for production

    • 64. Pushing our express app to Heroku

    • 65. Thank you

    • 66. Follow me on Skillshare!

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.





About This Class

Welcome to Full Stack Web Development for Beginners!

This course is designed to teach beginners everything they need to know to build full stack websites and applications!

This is part four of this huge course, teaching you all about Node, Express, Mongo, Mongoose, Routing, Templating, Authentication and deployment!

This course is all about moving to the back end of websites where you will learn lots of amazing things.

We start off with Node and the Express framework where we set up a travel booking application called let’s travel.

We will build this project throughout the course so everything you learn will be immediately put into practice.

Node and express are really popular and learning these technologies will leave you in high demand.

After this, we move onto routing and templating.

This allows us to switch between pages and navigate through our app, along with setting up templates to display not just content we have created, but also to render data from databases too.

And databases are what the next section is all about, where we look at MongoDB and Mongoose.

You will learn so much including modelling our data, create, read, update and delete actions, along with filtering and aggregation to get back the exact data we need.

After this we push on with styling and adding lots of nice features to our project, along with learning many next generation Javascript techniques from ES6 and beyond.

You will also learn how to allow users to upload images, and how we can save and retrieve these images from cloud storage.

Of course, most apps nowadays need to deal with user accounts and authentication, and this is something we will also learn about while applying all this to our project.

 You will learn how to create user accounts, logging in and out, validating the users information, authentication, storing passwords safely and so much more.

We finish off our app by allowing the user to place orders and save to the database.

Then we create an account are where the user can log in and see any bookings which they have made, and also admin users can go into the admin section too to see a list of all orders from the site.

 The course ends by showing you some security tips and recommendations to prepare your application for production.

 We then push our app to a live server for the rest of the world to see.

All while explaining things in a straightforward, simple to understand way which even beginners will understand, along with reinforcing things with a fun, yet challenging project as we go.

I hope your excited to learn about Javascript, Node, Express, Mongo, user accounts and authentication, routing, deployment and so much more, in the final part of this course….

Meet Your Teacher

Teacher Profile Image

Chris Dixon

Web Developer & Online Teacher

Top Teacher

Hello, My name is Chris and I am a Web Developer from the UK. I am an experienced trainer leading web development bootcamps and also teaching online courses.

My main areas of interest are Vue.js, WordPress, Shopify, Javascript, eCommerce, and business. I am passionate about what I do and about teaching others. 

Whatever your reason for learning to build websites you have made an excellent career choice.

My personal motivation was to become my own boss and have more freedom and flexibility in my life. I also enjoy the technical challenge it provides and the way it constantly evolves. I built my first website back in 1999 and I have watched the web evolve into what it is today.

I try to make my courses enjoyable and try to remember what it was like wh... See full profile

Class Ratings

Expectations Met?
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.


1. Welcome to the course!: Welcome to Full Stack Web Development for beginners. This course is designed to take you from a beginner to a web developer capable of building not only the front-end user interface, but also to design and build the backend to interact with too. Who am I? My name is Chris and I will be your instructor throughout this course. I am a web developer and also the producer of lots of tutorials, teaching thousands of students the skills they need to build websites and applications. This is the fourth part in the full series, where we will continue to build on everything from the first three parts of this course. This course is all about moving to the backend of websites, where you will learn lots of amazing things. We start off with node and the express framework, where we setup a travel book in application called Let's Travel. We will build this project throughout the course. Everything you learn will be immediately put into practice. Node and Express are really popular and learning these technologies will leave you in high-demand. After this, we move on to routing and templating, which will allow us to switch between pages and navigate through our app, along with setting up templates to display not just the content we've created, we'll too also render data from our database too. Databases is what the next section is all about, where we'll look at MongoDB and Mongoose. You will learn so much including modeling our data, create, read, update and delete actions, along with filtering and aggregation to get back the exact data which we need. After this, we push on with styling and adding lots of nice features to our project, along with learning many next-generation JavaScript techniques from ES6 and beyond. You will also learn how to allow users to upload images and how we can save and retrieved these images from our Cloud storage. Of course, most apps nowadays need to deal with user accounts and authentication. This is something which we'll learn about while also applying all of these to our project. You will learn how to create user account, login in and out, validating new user's information, authentication, storing passwords safely and so much more. We finish off our app by allowing the user to place orders and then save them to the database. Then we create an account area where the user can log in and see any bookings which they have made. Also admin users can go into the admin section to see lists of all orders which have been placed. This course ends by showing you some security tips and recommendations to prepare your application for production. We then push our app to a live server for the rest of the world to see, all while explaining things in a straightforward, simple to understand way, which even beginners will understand, along with reinforcing things with a fun yet challenging projects as we go. I hope you're really excited to learn about all of these things, in the final part of this course. 2. What we will be building: In this section and for pretty much the remainder of this course, we're going to build the niche travel application, when user can login and make bookings for hotels in various countries. This is going to be the homepage, which is going to be the starting point where a user can search for hotels in different countries. We can also add the number of nights and also the number of guests, as well as certain filters such as the star rating, and we can also solve the hotel's price wise from low to high or high to low. Further down, we're also pulling in some random hotels from the database and restricted needs to be the first nine. The user can click on any of these hotels and find out more information. He will get an extended view of the hotel. We also get a description and then at the bottom, we get the chance to then search for this hotel with the current availability and also the current price. If we go back to the homepage further down at the bottom after the hotels, we also have a list of countries where we can filter down the hotels by the various countries. If we click on each one of these, we can then see each hotel which is available for that particular country. Along with these filters, we can also click on the "All Countries" and then see a list of all available countries which we have hotels available for. Once we add new hotels as an Admin, these countries are automatically updated on the front-end too. So we don't need to worry about adding all these in, each time we add a new country, as well as these countries. If we go back up to the hotels, we also have a link to see all the available hotels. If want to scroll through all the ones which you have on the database rather than filtering down by the countries by using a Search. Service application will be a node-based application using the express framework which we'll learn about in this section and the forthcoming sections two. Will also be using various technologies to join this project, such as MongoDB to store our data. We use Mongoose for various things such as structuring our models or other data. Along with all this, will also have the facility for the user to go ahead and login. We can log in with an email and password. So let's listen now. Will also be using flush messages, just like you see here, to give the user some feedback about when a login or logout, along with the admin to be able to see when a hotel has been successfully added to the database. Once we login, we now have an account section which we can click on. We can also check out the current bookings which each user has available. Along with this, if the user is an admin, so let's go to '"/admin". Currently, the username and password which I've entered is down as an admin. So we now have access to this admin section of the website, which is going to be the back end where can have some administrator privileges, such as adding new hotels to the database, which we can do with this form here. The admin can also edit details of a hotel or completely remove them from the database too. All we need to do is, add the hotel's ID, or we can search by the hotel name, if we're not sure of the ID. Back to the admin, we can also view all of the available bookings which being placed by all users. Once we're logged in as a user and perform search, let's search for Jamaica, seven nights, and we can add a date, number of guests, the star rating, and also the price filters. We can click on "Search" and then we've taken it to the search results. So this is the hotel which matches our filters and we'll also have a section on the right-hand side which calculates the total per person and as well as the total cost of the booking. We can then continue through to the confirmation screen which provides the full description of the hotel along with the facility to place an order. Once it is placed on and taken to our counts and then we can see down at the bottom that our order has been added down at the bottom with a unique order reference. If you go to the admin, it should also be added inside here too because we're logged in as an admin too for this current user. We can also go to View bookings, and then see the bookings placed down at the bottom too. If we're to go ahead and log out and then try this admin section. We can see we're redirected back to the homepage because this route is protected. So during this project, we're going to be learning a variety of things. As I mentioned before, we'll be using node for the back end, express as the framework to build this project, Mongoose and MongoDB for our back-end data, route into navigate through our projects along with the MVC pattern which will allow us to add some structure to our project too. Along with this will learn so much more including authentication, how to keep users logged in using sessions, along with so much more, and we'll find out all about this in the upcoming sections. So we're going to kick off this project in the next video, where we'll take a look at node and MPM along with installing this on our system. 3. What is Node & NPM?: Welcome back. If we head over to nodejs.org, this is the official homepage of Node.js, which we'll be using to build this final project. We see at the top there's some information about what Node.js is. Basically, Node.js is a JavaScript Runtime, built on Chrome's V8 engine. What exactly does this mean? Well, V8 is engine which makes JavaScript work inside the Google's Chrome web browser. When we've been using JavaScript so far on this course, it's been running inside the browser. Chrome uses its own V8 engine, and also other browsers have the own version too. Historically, inside of the browser is where JavaScript is run, on the client side. However though, since Node.js was developed, we can also write JavaScript code, which runs on the server too. One of the key things about V8, is that it can also run anywhere. Not just inside of Chrome, making it available to work in other applications too, which is wrote in the C++ programming language. With this, Node.js was created using the V8 engine, which will allow our JavaScript code to be run on the server sign two. This was huge for a lot of developers who already knew JavaScript, as they can now write the front-end and also the back-end of applications using the same language. Before this, we would have to learn another server side language, such as PHP. Why do we want to run our code on the server? This is because it allows us to create dynamic web pages. This means, the web page is created on the server first, and can also include any dynamic data, pulled in from our database or other sources. Also, it can check if the user is logged in, for example, before sending back any sensitive information. If you've not already done so, make sure we click on the download button for the current version of Node and go ahead and follow the installation instructions. This on our system will allow us to run Node locally and create a web server on our own computer for development. When we're downloading Node.js, it will also include npm, which is the Node's package manager. This is the collection of thousands of packages which we can use with Node to build almost any type for project which we wants. Also on [inaudible] 2 , if we build something ourselves, which we think may be useful for somebody else. We can then bundle it into what's called a module and also publish our own module two on npm. As we go through this project, we'll be using npm modules to add functionality. Such as a module called passport. We search for passport, this is a Node module which we are going to be using to provide user authentication, so users can login with a email and password. We'll also use many more npm packages too, as a progress, to allow our passwords to be encrypted, to allow file uploads, for security and many more, which will discover soon. This is Node and npm and an overview of what they can do. We'll discover more about them as we go through this project too. If your Node download is now finished, go ahead and click through the installation steps to install on your computer. Then I will see you in the next video. 4. Static v dynamic web server: You may be thinking, why are we using a web server to build projects? Haven't we gone fine so far without one? Well, this is a fair points among which I'll try to explain in this video. In a general way, we can categorize our websites into either static or dynamic. On the screen here we have our shape matching game opened up in the index.html. In all of our previous projects so far, if we open up the index.html and also opening up inside the browser, we have our HTML content. This HTML is all static as the content does not change. Yes, we may have some shapes appear in when the game starts. This is all done in the browser by using JavaScript. Inside the browser, if we go to right click and view page source, this will open up in a new tab. This is the exact same code displayed here as we see over in Visual Studio in our HTML. Even if we uploaded this project to a web server and made it live on the web, all of this content is still static and we'll get back the same results from the server. Basically in a static project like this, the server will send back what we gave it, such as the index page. Dynamic web pages on t [inaudible] he rondo can come back from the server a lot different than the code we can see in our text editor. If we go over to the finished version of our troubled projects and also open the browser. So don't worry about [inaudible] , how all this looks. We'll learn about all this code during the next few sections. I'm going to go over to one of the hotel templates, which is inside views, and then if we go to hotel.pug, let's close it up. Again, don't worry about all this complicated code. For now though, I want you to concentrate on one thing. This is the hotel name, which is in a level three heading. The syntax might look a little confusing because of this shorter h3. But this just a h3 elements we've already learned about. After this is hotel.hotel_name. If we go over to the browser, we can see the hotel's actual name, such as Hotel 11 or Hotel nine, rather than this hotel.hotel name, which we'll see in Visual Studio. If we go to the browser, we can see the hotel's actual name is also available in the source. If we go to right click Inspect and then click on our hotel name, go to the elements and struck this down. Here we can see our outputted HTML which is returned back from the server. We have our h3, which we can also see here. Both is dynamic data has now been replaced with hotel name. Here we see that the web server this time is taken our hotel template from Visual Studio and filled in the missing data with data from our database before returning back towards in the browser. This is what dynamic web pages are all about. Static sites, just like the one we've seen before with the Shape matcher, a totally fine for simple applications. Even ones which still use API data too, such as our song finder. But dynamic science is perfect when we want to change data before sending it back to the browser. Or for security related tasks, such as handling sensitive information from the user. As we don't want it to be handled inside the browser. Hope it make sense. Next we're going to get up and running with our project using the Express framework. 5. Express.js and express generator: For this project, we're going to be taking advantage of a lightweight framework for Node called Express. Express is a really popular framework in the Node community, and it's the ideal platform for us to begin our project. Over in the homepage which is expressjs.com, we can see this homepage, as it says here, is a fast, and unopinionated, and minimalist framework for Node.js. This means it does not assume how our project will be. We are free to basically take advantage of what Express provides without having to adhere to a lot of strict rules, which a lot of other frameworks force upon us. It's minimalist, which means it provides the base features we'll almost certainly need, such as a web server, route end to switch between pages, error handling and templating, boost any extra functionality is up to boost the ads by using the node package manager, which we looked at before. Express provides a web server which we can use to serve our pages, and this also serves them to all browser with the dynamic content just like we looked at in the last video. Even installed in Express 2, is done as an npm module. As we see down here, we have the terminal code to set the server as a node module, so we can set things up manually, or Express also provides a generator. We have everything we need to get going. If we go to the menu and Getting started, hover over this and then we can click on the Express generator. We need to install this via npm, so I'm going to head over to the terminal to install. Windows users can open up the PowerShell program for the stage, or any other program which you may prefer. I'm going to open up iTerm and make us a little bit bigger. Before we continue, we need to make sure Node and npm is correctly installed. We can do this by typing inside of the terminal or inside a PowerShell. We can check Node is correctly installed by typing node -v. If we see a version number here, it means the Node is correctly installed. We can do the same with npm -v. Again, if we have a version number appearing, this means that node and npm is correctly installed. If you don't see the version number or you have an error, do make sure to go ahead and re-install Node, and make sure this is in place before moving on. We can then go ahead and install the Express generator using npm. So type in npm install exepress-generator, and then dash g at the end. Mac users may also need to add the sudo keyword before if you hit an error. Just before this, we need to add sudo and then "Enter", and this will then prompt us for the password, then hit "Enter". Now is, we'll go ahead and download the Express generator from npm. The dash g flag which we add at the end of here, will install this package globally. This means it can be used in any project, not just the one we are creating. Now we need to navigate to where we want to create our projects. I'm going to be adding mine to the desktop. At present, I am in my current user directory, so I'm going to use cd to change the directory to the Desktop. Hit "Enter" and now we can see we're inside of the desktop. Of course, you can change it to be any location which you prefer, I'm just keeping mine on the desktop for ease of access. Now to create a new project in this directory, we can run this command. So express followed by the name of our project, I'm going to call mine lets-travel, and then dash dash view is equal to pug, hit "Enter" and let us go ahead and create our projects, which is also using the pug templating language, which we'll cover soon. If we scroll up inside the terminal, we can see a list of files and folders which have been created for us, and also some instructions on how to get started. I'm going to be using Visual Studio's built-in terminal from now. I also recommend you do this too throughout this course. If you prefer, you can keep on going in a separate terminal, but you will need to go ahead and first change into the current directory for the project. Then you would need to run npm install to get all the dependencies, and then start the application with these commands down at the bottom. If you are following along in Visual Studio Code, we can now close down the terminal, the browser, open up Visual Studio Code, and then drag inside our project folder. We can open up Visual Studio as built-in terminal, by going up to View in a sub menu, and then go down to Integrated Terminal. This will then open up the terminal down at the bottom, listed are our terminal commands. This also has the benefit of having our directory automatically setup to the column project folder on the desktop. We don't need to navigate to where our folder is located. We're going to take a better look around all of these files and folders soon, but for now, if we open up the package.json and then close the sidebar, inside here we see some dependencies, which inside of this dependencies object just here, which are needed for this project. These dependencies are node modules which you can install using npm install. Down in the terminal, run npm install, hit "Enter" and then give, say a few moments to run through and pulling all the packages we need from npm. npm install will grab everything we need listed inside of this package.json, and then place them inside of our projects in a node modules folder. Also, when we add more modules later, again we will use this npm install command, but followed by the module name we want to install. Great. Once this is done, this should now be a node_modules folder. If we open up the sidebar, if we open this up, we just got a drop-down, we see listed everything which we're using for this project. It will have things such as a debug module. We also have express which is just here, and also pug, our templating engine amongst others which we'll also use. Now all that is left to do, is start up our web server and open it up inside the browser. Still inside this package.json file, up at the top we have something called start inside of our scripts. We can use start script inside the terminal, to then go ahead and kickstart our application so we can view it in the browser. Down inside the terminal, let's run npm start, hit "Enter" and then open up the web browser, which you want to use. Navigate to localhost, colon 3000, hit "Enter" and now we can see our basic Express up is now running. But how do we know it's port 3000 which node is running on? Well, if we go over to the package.json, the start command has a file path of bin, forward slash, www. If we open up this file inside the same bar, inside of this file is a variable which is set to port 3000. Here we have a variable called port, which is set to be port 3000. Also, if you happen to use port 3000 for anything else, you can also change this number to be something different, such as 3001. Its file structure and setup is a little different to what we've used so far. In the next video, we'll take a better look at what we have here in our Express Generator project. 6. Express project structure: The project structure which we have here can look a bit intimidating if you're used to using static websites. However, it's not too bad once you get used to it. If we open up our sidebar on the left-hand side, I'll make it a little bit bigger. From the top we have the bin folder, which is used for any startup scripts. We touched on this in the last video where we seen these start script inside of the package.json file, which then points to this www file, which contains our startup scripts. This file inside here sets the port number we want to use, and also goes ahead and sets up a HTTP server to then serve up our projects. Under this we have our node modules folder, just down here. This contains all of the packages or modules which our application needs. Each time we install a module from MPM, it will then appear inside of here and also be listed inside of the package.json file as a dependency tool. Since these modules also listed in the package.json file, we can even remove or delete this full node modules folder, and an MPM install command will then again, add this back to our project. This is useful for things such as storing our project on GitHub, as the node modules folder can often get really big and we don't want a huge folder like this saving to GitHub or elsewhere if we don't need to. Download this, if you're closing node modules, we also have a public folder. The public folder contains our static files, such as any images, any style sheets, and also any JavaScript files or libraries for the front end. Here we can add our project images, any custom third-party libraries or frameworks such as Bootstrap CSS and JavaScript files. This folder is not for any JavaScript files or the server, such as our page templates or anything with sensitive information, such as an E configuration files. Under the public folder, we then have our routes folder. Each folder will contain one or more JavaScript files, which handle what to do when a user visits a certain URL. As an example, if we open up this index.js, and I close the sidebar, you will see the router.get, which handles the homepage. Inside a router.get, we first see the route of forward slash, so when the user visits the home router or forward slash, these enrages a function which then goes ahead and renders the index templates, which we want you use. Then after this we have a objects where we'll pass the page title of simply express, and later on we'll also pass different information such as variables to our page template too. This moves on to the views folder if we open a sidebar and then open up our views, which is a view which the user sees. It contains all page templates which are created on the server before then sending back to us. All these files have the file extension of.pug. This is because we're using the pug templating engine, which also used to be known as J2. You may come across some j references in the documentation or one searching on the web. You can use other templating languages if you prefer, such as EJS. But this will be up to you to implement if you want to make this change. If we'll open up the index.pug template. This is a template being called from the router page we've seen before, so this is the index which rendered when a user visits his home route. Block and extends, which we see at the top of the file, we will look at this soon. But it's h1 and also p elements are what we see when we visit the homepage. We have the title and then the text of welcome to, and then the title. Inside of Chrome, if open this up, this is the text we see inside of here. H1 equals title, is the title which is passed from the router. Again in index.js, this is the title we see just after we declare which template we want to use. The text of express is then being passed to our index and that's why we see the text inside the browser. Below this we have a p elements with a text of welcome to and this will be express. We can also use this as a variable inside of a string. We'll cover all of these templates in syntax in the next section. Down after the views we have the app.js file. This app.js is the app's starting point and basically the main page which connects everything together. It loads up everything we need for the project and by default import any packages we need lope at the top from the node modules folder. It also import our routes from our routes folder, which we can see here, by these file paths, and then stores them inside of a variable we see as below. It then goes ahead and kicks off our new express app instance and assigns it to a variable called app. After this we set pug view engine, which is used here, which declares which templating language we wants to use. After this we have app.use on various lines. This is used to mount any middleware to our application. We'll look a middleware in more detail later. But basically middleware is a series of actions or functions which we can run our code through. An example could be when a user logs in, we could add some middleware to validate user's information before moving along to the next stage. But again we will look more into this when we are at our own middleware to the project. If we scroll down, next up we have our routes, which again is middleware and these are the two variables which we had before, which is just about the top. These are the variables which link to our file path for the router. It would declare one wants to use our index router when the user visits any of the home routes, and we also have a default user's route too which has been setup with Express Generator, and these routes are stored inside our index and uses.js files. Scrolling further down, we also have some error handling, which again is middleware. App.use without a file path, will make these error handling functions available for all routes in our site. Finally down at the bottom we have module.exports equals app. This will make this file available in other parts of our application if needed. Back to our sidebar, the last files are the package.json files. Inside of our package.json, which we've briefly looked up. We have the information about our project, we have our startup scripts to run our web server. We can also add our own scripts here too, as a shortcut to type in out this longer command in the terminal. We also have the name which we set and also the version number which we can set too. Further down, we have the dependencies which we looked at before. These are the node modules, mid file projects and we can also add dev dependencies too, which is the modules we need for development only, and these will be ignored for production. Soon we'll be installing in the node mom package, which will be a dev dependency so I'll show you how to do that soon. If we open up the sidebar, we also have a package.json. For example, inside of our package.json, we have the Express dependency, which is just here. This says currently at the time of creating this app expresses our version 4.16.0. The tilda icon you see just at the beginning here, means we won't express version four, but we also want any minor update of versions two. Ie we can take 4.17 or 4.18 and so on. With this in mind, if we go over to this package-lock.json. And then if we do a search for Express, but then taken to the Express section of this file, we see the actual version is locked in at 4.16.3. Also, this module itself has dependencies too. If we close down this terminal and then scroll down you see we have this required section just here and express also requires a lot of different modules too, such as cookie, debug, escape HTML and also lots more. This is why when we go over to our node modules folder and open this up, there is lot more folders listed here or Lamar modules than we originally seen if we just go to the package.js. Let's close it down. All of our dependencies inside this package.js also has dependencies too and these are listed in the package-lock.json. This is an overview of what is included in the project to begin with, I know we've said it quite a few times already, but really don't get overwhelmed by all of this if it's new to you. We'll become a lot more familiar with the setup of the next few sections. 7. Using Nodemon: We are now going to install a node package, which will save us a lot of time during this project. If we go over the views inside the menu and then go to index.js, views, index.js, and then you can go ahead and make a small change to our text inside here. If we say, welcome to, and then say, let's travel. Give a save and then open the browser and then reload. We see this change has been reflected inside the browser. This is fine, and this is the result which we would expect. If now go over to a script file, such as inside the routes and then go to the index.js. Let's now make a change inside of here. The comma is out, it's res.render,/. Remember this is the line which renders our homepage or our index templates, and then instead if we go to the line below, say res.send and then the text off 'hello'. This will simply send a string of texts to the browser. Give a save and then reload and see that nothing happens. This is because if we make changes to a script file, we need to restart the server. We can do this if we go over to the terminal remember this is view, and then integrate the terminal, we can close the terminal downwards, Control C, and then we're taken back to our directory, and then again use npm start, to begin the server once more. Hit Enter, then once it's running, we can go to the browser and Hit Reload, and now the terminal has restarted the server. We'll now see the text of 'hello' has now been updated in the browser. Although this works fine, it's a bit of a pain to keep restarting the server, every time we make a change inside those files. To make things easier, we can use a package called nodemon. If we go over to nodemon.io, this is the homepage for the nodemon package, which we're going to be using. Nodemon will watch for any changes in our source code and then automatically restart the server for us. We can even install nodemon, as it suggests, using this npm install command, the name of nodemon for the package and we may also use this -g flag when installing the express generator, and it means we can use it globally in any project and not just the one we are currently working on, or alternatively, if we just want to use it in our single projects. This is simple to setup too. We can head over to the terminal in Visual Studio Code and then close down a terminal again with Control C and then run the following command against our npm install, and then this time we want to say --save-dev and in the name of our package, which is nodemon, Hit Enter and it will go ahead and grab the package from npm, save dev we'll save this in our project as a development dependency. Meaning we can use it during development, but is not required when we push the app to production. Give them moment to install and then once this is done, if we go over to the sidebar and open up the package.json. Inside of here we still have our dependencies, which we've seen earlier but further down we also have our devDependencies and they're listed as our nodemon package. Now for this to work in our app, we can create a script, just like the startup script, which we have at the top here. This one I'm going to call devstart. Add a comma after the first line, and then we can add devstart. This is the alias which we're going to give to this command. Add a colon, and then inside the quotations, we're going to add a command which is nodemon and then the same path which we have used here./bin/www. This is going to essentially run the same startup scripts but this time we're watching for any changes using nodemon. Give that a save and now we can go ahead and start our servers. This time if we go over to the terminal, make sure the server is closed down and then this time can run npm, run devstart. Of course devstart is the name of our script which we have just here. Hit enter, once it is up and running, you should see the green line of code just here and then over to the browser, hit reload and now everything should still be working. If we again go over to the index.js file and then make a change. Let's say 'hello again'. Save and as soon as we hit save, we can see the terminal at the server has restarted. Then reload the browser and now we'll see our text has been updated without us having to manually update the server. Let's now reinstate our res.render, so we can remove the res.send and then command and forward slash to now uncomment out this index page, save this, and then reload and refreshing the browser will now show these changes without having to close down the server and restart. 8. Serving static files: For this project, I have provided some images which you can also use, such as images for the hotels, the countries, and also the logo. You can of course choose your own if you prefer. The ones provided are inside this folder called images, which I have here saved onto the desktop. If you open up this folder, we can see we have the beach, which is one of the main images on the homepage. We have our logo and then our country's images and hotels organized in two folders. Let's also open up the project folder. Double-click on Let's Travel and then inside here, we can go to public, and then to images. Then if we select the four items from our images folder, and then drag these over to the images folder inside of our projects, so this is over and make sure these are inside of the images folder, rather than just the public section. We should be able now to see these images, if we go over to Visual Studio code. Open this up and then the sidebar and then inside of a public, we now have the images inside of images folder. If we go over to the index.pug, which is the main homepage templates, we can test this out by adding a image. Underneath our text of Welcome to Let's travel. We can add our image, we can add some attributes inside the quotations to set the image to use equal to our images which is the folder. Then let's go ahead and add beach.jpeg, which is this one just here. Note we don't need to add the public folder to our file path and then save this, open up Google Chrome or your browser, reloads and that's our image of the beach, great. Now all of our images and also our project structure is now in place. In the next section, we're going to dive deeper into our project by looking at routing and templating. 9. Introduction to Pug: We have already talked about how we will use templates to create our projects. These templates will be a combination of HTML, JavaScript along with any dynamic data mixed in, such as a hotel name, which we looked at in the last section. We know that we can't do all of this with the standard HTML files. So we need to use a templating language which compiles all of this into HTML. I'll be using a templating language called Pug to do this. It may look a little strange to begin with, but it's actually simpler than normal HTML tags. To see how to use Pug, let's head over to our index.pug file. There was a sidebar to a give small space, and we've already had a quick look here with the p elements and also with an [inaudible] image. We have extends and block at the top, which we'll come back to soon. For now let's concentrate on the features of pug. Generally, using Pug is just the HTML opening tag to make for the shorter syntax, just like this p element with the text of a text-based elements work in a similar way, such as add in a heading. So let's add a h1, let's say title, over to the browser, and then reload and we have a level one heading down here. Attributes are added just like with normal HTML tags. But instead with Pug they add it inside brackets. If we wanted to add a link and then at the href, we do this inside of the brackets, and then the rest is just added as normal. So let's add a link to Google. So www.google.com, we can also add our classes. So let's add a class of button, and then afterwards we add our text outside the brackets, which you want to add for the link. So link to Google text. Save this and then reload and now have our hyperlink at the bottom, and if you click on this, it will work just like normal HTML a tag. Back over to our project and the index.pug. The indentation is also really important when using Pug. In normal HTML, indentation is only really for readability. But when using Pug, it's necessary to use it to show what level each element is on. For example, if we added a div to contain this title on the link, just like this, and then if we go to the browser, and then go into developer tools would right-click and inspect, and then select this div just here. So this is a div which we just added, and the developer tool shows that the div title and also our hyperlink are all on separate lines. They effectively all at the same level, we don't have the title and the link inside of this div tags. But if we go ahead and indent the h1 and the link, and then refresh this. We now see that the div opening tag and closing tag now surrounds our title and link. So the indentation causes these two elements now to be nested inside of the parent div. Another thing about indentation inside of a pug file is only mixins, which we'll cover later, and also this block declaration at the top, and extends can be at the top level i.e. on the far left of the file. If we move over a nav element, so our link for example if we move this over to the left of the file, save this and then reload the browser. We now get a error saying only named blocks and mixins can appear at the top level of a template; This is basically because this file will be used inside of a NAV file. So this indentation keeps everything right when the HTML is compiled. Let's go ahead and reinstate this link, and clear the error. Something you may have noticed is above, we also use a equals for this title. This is because we can also include JavaScript in these Pug files too. If you remember, the title was passed from our router, which was index.js, just here inside of this title. So this is JavaScript being passed to our template in the index.pug. Therefore, we need to use the equals rather than just a plain text element, just like this and also our p elements just here. This title is also displayed in the browser sub too about the top here. Use an equals will also render to the screen the result of any JavaScript. So instead, if we say rather than title, add some JavaScript of 5 plus 12 over to the browser, we have the results of 17. But instead if we go ahead and remove the equals, you got to save and then back to the browser. This now displays as a text string of 5 plus 12 rather than outputting the sum of 5 plus 12. So let's reinstate this back to title. So you don't have to remember this but I'll put in the result like this is called buffered code. It is also unbuffered code too which does not directly add to the output; This can be any normal JavaScript with a dash prefix. So for example, we can add a dash and then add any JavaScript such as a constant of name, and it's our name to be Chris, and then this can be used where we want to place it. So h1, we can place our title with our variable of name. Since it's a JavaScript we'll also need to add the equals and test this out, and then down at the bottom there's our variable name of Chris. So this unbuffered code, it's just basically declaring line of JavaScript, and then we can go ahead and use it anywhere we want inside the templates. This JavaScript can be pretty much anything. So we could have an array of foods, cheese, eggs, and chicken, and now we have this array. It gives us a chance to take a look at the special syntax which Pug provides for creating a for loop. To do this, I'm going to add this at the bottom, indent this the same level as the link, and then create a unordered list for our foods. Indented one more level we're going to create a loop with each food in foods. So foods is the name of our array which is just here, and then each individual item in the array is going to be stored inside this food variable. So after here we can set our list item to be equal to food. Again this is JavaScript, so we need to add the equals symbol. So we don't output this as a string. Say this, and then test this out. We now have cheese, eggs, and chicken at the bottom. This output can also be mixed with an eText too. So rather than just the outputted individual food, we can add a string of I love, and then add plus food. Actually about a space just after there and try this out, and our text is also now mixed with our JavaScript variable; This is just a overview of what Pug can do, and it really is simple enough once you get used to it, we will use a lot of Pug features for this course. However, if you prefer to take a deeper look now, you can head over to Pugjs.org and take a deeper look, at the top of this file we also have this extends and also this block content section. We have not yet discussed what this means yet, but we'll go ahead and cover this in the next video. 10. Template inheritance: We have both block and extends keywords, inside the pug files at the top just here. If we open up our layout to pug file, which is available in the view section, click on layout the pug. This layout file has no extends keyword at the top. This is because it acts as the main pug templates. The files will then extend this main layout. This is why we can open up our index the pug and also our error the pug as well, which is available in the same folder, and then see the extends layout at the top. If we go back to the layout the pug file. There is also a block contents section here down at the bottom. This is what it sounds like. It's basically a block of code. Any of the files such as our index the pug can go ahead and replace this section called content. Inside of our index the pug file, we'll open this up. All this section here, basically everything from our unordered list all the way up to our title, will replaced inside of the block or inside the space which we specify inside the layout. We can also have multiple blocks too, each with a different name, such as footer or a sidebar block. These can also be added to another file, and then referenced by the block name, and the same way as his content section. We freeze, then add anything else around this block. For example, above the contents and we can add some text. Above the contents, and then below it, below the content, and now if we go to the main index page, and then reload, we see at the very top we have the text of above the contents. and then at the bottom we have the text of below the contents, and then everything in the middle, right through from the title down to all unordered list isn't provided by this block content section, which is an overridden by the contents of our index the pug. Once you understand that, we can now create sections of our code inside of a layout, and then we can outsource the contents to a separate file, skip all code, more organized, more maintainable, and we can also reuse these sections of content too in multiple files. Now let's go to the layouts, and delete these two p elements which we created, and then give that save. This layout is useful for anything we want to display in all of our pages on our site, such as adding a header and footer. We can then replace the main content down here or a new sections by adding more blocks. Now we know how our templates are laid out. Next, you will get the chance to get some practice by creating the header section. 11. Time to practice: Creating the header: When dealing with anything new, just like Prog , we really began to get better when we practice on our own. Without just following along. Here we can see the final version of the projects, which I would like you to go ahead and create this header section from the top navigation, which includes the logo and also the links at the top, right down to the main beach image just here. If you feel confident, you can also add the search form two, which is in the middle. Just as a guide for where you're going. In this, we'll need to go inside of auto-layout dot Prog file, inside of the body section. So just above this block content. So it's at the very top of the page. I'll be going over all of this in the next video. So don't worry about messing up. It's all good practice. So I would recommend you pause the video now on this final version and then it give this a go. 12. Solution: Creating the header: I hope you managed to give that a go and hopefully have some header content. Now on the screen, I'm going to go ahead and create my version of this header. If yours is different to mine, you can either change it to be the same as ones created in this video or keep yours as you would like. Either way is fine. I would maybe recommend though keeping the same class names as we use in this video so the CSS matches up later. Let's begin over any layout docktype file. In between the body section and the block content. I'm going to begin by creating the header section just like we would normally do with HTML. Nested inside within this nav element. This logo can be a link. This is so the user can click on it and then be taken back to the index page. Our a for our link, which can include the href inside of the brackets which simply links to forward slash, which is the homepage. Then one level in from our link. If we go ahead and add our image, this will then be clickable and also link to this homepage which is forward slash. Inside of the brackets we add our source, so SRC and the sequence be forward slash images. This is logo.png. We can add a class or an ID to our element. By adding this inside the brackets as a attributes or we can add it just after the element name. Add image and the harsh and logo. This will give the ID of logo for this image. Then just after this we can go ahead and create our another list which is going to be for our sign up and login links. This needs to be at the same level as our surrounding link above, so ul followed by our list items. If we want to make these links, we need to indent the a tag plus the href. We don't have these templates or these routes setup just yet but we can still go ahead and link these to sign up. With a text of sign up to and then do the same below add our next list item at the same level as the one above. Turn this into a link. This time this one is going to be for login, which is the routes of forward slash login and the text of login to. If you've created this and you've not added the href in, I would recommend you keep yours consistent with mine so it has no problems further down the line. I added forward slash login and also forward slash sign-up. That give us save name over to the browser. There's a logo and then our two links at the top too. The next thing to do is to create our form input for our search. Which is where we can type in the destination, the duration, the departure dates and also the number of guests that we want to search for, so we do this just with a simple HTML form. This form is going to be in a surrounding div. This div needs to be on the same level as our nav element. Come down for the nav element and then begin this at the same level. When creating a div with the class, we can even create the element just like this and then add the class name as a attribute or instead we can have a shorthand which is simply dot and the name of our class. If we wanted a div with the class of search nav, we would just do it simply like this. This will then be outputted as a div with this class. Then inside we can nest our form. This form is going to be made up of a series of form input and each one is going to have a surrounding div of input underscore wrapper. This will make each input block level, so they appear on their own line. Then we need to label for our first one which is going to be destination. We add the for attribute or destination and then a text of destination. Then we can add our input, the type of text, the idea of destination which will match this label just here. The name of destination too. I will just change the style so it's a little bit more readable and then the required attribute on the very end. Save this and then let's see how it's looking in the browser and now we have our destination form input. Now this is working, we can go ahead and copy this input_wrapper and then paste this in and make sure this is at the same level as above. This one is going to be for the duration. Change the label to duration, the text and then we can add nights inside here because we're going to be sign the duration per night. The input type of text is fine, the ID needs to match alteration and the name of duration too. This field is also required so we can leave this in too. The next one is going to be for the departure date so the label text. This time the input is going to have the type of date so it drops down as a date picker. The ID of departure date too and then the name, date of departure. This is going to be CamelCase. This field is also required just like the others. I'll do this the same one more time this one is going to be a number field. The input type of number because this is going to be for the number of guests, so number-guests. The name of number of guests and then the ID which must match this label of number guests. I have a typo though so change that. Then finally the name, again in CamelCase of number of guests. Let's check this out in the browser. Great, that's our four inputs. We can see if we click on the date, we now have a drop-down date picker. It should be a input type number which is on our two text fields at the top. Back to our layout, after these first four input we're now going to change this up. We need a couple more and one is going to be for the star rating. This is going to be a select input with different options through from one to five. We are then going to have an input with a select again, which is going to be for sorting the price from low to high or high to low. Then finally the Submit button at the end is going to use the same input wrapper, so.input_wrapper. This is a select with a name equal to stars. Remember from earlier the select input do need to have an option to select. Add our first option inside here with a value to then pass to the server once selected. It's just going to be simply a number for the number stars and the text of min one star. We can go ahead and copy this in and paste in four more times. The second one is for two-star, 3, 4 and 5 and also the same for the text too. The last input, again these ones have the same input_wrapper so we keep the styling consistent. This will also be a select and this is for the price sorting from low to high or high to low. We can add the name of the select to be sort. Paste in the option with a value of one. This is going to for the price set from low to high. We're also going to paste in the same but this time option can have a value of negative one. This is because these are the values which you required when searching Mongo database to then sort the return queries from high to low or low to high. We'll see this in more detail later on. This can be also change. This time let's see price from high to low. The last input also needs the input wrapper and this is the Submit button. Button with the type of submit and then the text of search.That should lead us now to form. Let's check for any errors. The star rating from one through to five. We have the price from low to high and high to low. Then I will submit button at the bottom. We also want this beach image be part of the header too. Inside this header section, just after the form, we need to make sure this image is indented at the same level as our navigation. If we scroll up and then go to our search nav and keep an eye on this line which we see in the text editor. Now we could start our image, so img. The source just as before, is going to be equal to forward slash images which is inside the public folder, the beach d.JPEG. Then let's bring up the block contents. Save and then reload the browser. Now, we have the image inside the header. We also have some cleanup work to do just below and this is only consent from the index.pugfile. Go over to index.pug. Then we can remove our examples from earlier. We can move out another list, our links and array. We don't need the image. We don't need the text or the title. Let's just leave in place the extends layouts and the block contents and off to the browser. Now, we just have the header content from our layout file. There we go. There is our header content now in place. Next we'll move on looking at using mix-ins, which are a great way to reuse the same code in multiple templates. 13. Mixins: One of the things we usually want to avoid when coding is repetition. If we reuse the same code more than once, it often makes sense to do things a little differently. Thankfully, Vue gives us the opportunity to use what is called mixins. If we look at the finished version here. Take our hotels here on the home page, for example. The same hotel structure which you see just here. Also the layout is used if we perform a search tool. Here we have our listed hotels which follow a same pattern. If you do a search and filling all the fields just on here, hit search. Where you see our search results follow a similar layout and pattern as our hotels on the home page. This is a good use case for a mixins even though the hotel data is different, such as the description and also the title, we can make parts of the mixins dynamic. It's really flexible to use. Over in the index dot pug file inside of Visual Studio Code, let's begin by adding the hotel info we need to begin. Starting with the wrappers and then link to all hotels. Just have block content, make sure you have this intended. Then we can add our outer div. Outer underscore wrapper. Inside here we also want to have a second wrapper for each individual hotel. Hotel underscore wrapper. Then the h2 of hotels. This level two heading is also going to have a link. Just after this we are going to add our link, which is going to link to all hotels which are available. Add a href, which is going to link to forward slash all. Then in brackets a text of "see all" you're going to save this and then go to the browser in the home page and then refresh. Down at the bottom we have our title of hotels and then we'll have a link which we'll wire it up later to see all the available hotels in the database. The reason we have this link to see all hotels, is because the hotels which will display on the home page are only going to be restricted to nine random hotels pulled in from the database. This is so the home page doesn't get too crowded when we have lots of hotels inside of our database. Now go ahead and add a dummy hotel. You can see how this is looking. After our links and at the same level as our h2, we can add a hotel wrapper, so dot hotel nest. Inside here we're going to have a couple of different sections. The first one is going to be for the hotel image. Hotel img. This is going to be the section which is going to appear on the left hand side and it's going to have a image of the hotel which we'll then link to the full hotel description. We need a link with the href. We can leave this empty for now because this data is going to be dynamic and it's going to link to the current hotel which we're viewing. After here we're going to add a image which is the main hotel image and we could just add a dummy image now. Forward slash images forward slash hotels. Then we can select any hotel we want from our public folder. Let's drop hotels down and you can choose any one of these images from there. I'm just going to go for hotel one dot JPEG, and just like this link above, this will also be dynamic too and the information will be pulled in from the database and then we can grab the correct image. After this hotel image section, let's add a new section surrounded by a div called hotel underscore info. This is going to contain information about the hotel, such as the hotel name, the star rating, the country, and also the price per night. The hotel name is also going to be a link just like this image, which will also link to the full hotel view, which will show a extended description. Add our surrounding link with an empty href for now. Our title of the hotel is going to go in a h3 element. We can add some dummy text of hotel one. A horizontal rule then separates the title from the rest of the information. Now it's just a case of adding some p elements. The first one is for the star rating. We can set it to be anything we want for now. Let's go for four. The country: Jamaica. Then finally the cost per night. Remember this is just some dummy data so we can see the structure. Then let's see how this is looking. There's our image section above, and then our hotel info with the name, star rating, the country, and also the price. Great. We now have a hotel on the Home page. We also need to create a view to link to you when the user clicks on this all hotels link. Let's go over to Visual Studio, open up the sidebar, and then inside the views we can create our new view called all underscore hotels dot pug. Inside of this template we also need to extend layout. We also need to add block contents. Now as you going to share a similar view to the hotel from the Home page. If we go over to the index dot pug and it will copy all the way from the cost per night right up to the hotel. This is the individual hotel div. Go to all hotels and then we can add our wrapper. So dot hotel underscore wrapper, indent it in one level and then we can paste in the code from the last video. Make sure this is just indented in one level and make sure our all hotels dot pug file is saved. If we go over to our home page, we now won't be able to see the view down at the very bottom. It is because we have not yet set up the routing to handle this forward slash all. But you can already see that we've repeated the same hotel code, both inside the all hotels template and also inside of the index dot pug. Now's our opportunity to reduce our code by moving this hotel into a mixin inside of the views folder, inside the sidebar. Let's create a new folder called mixins. Inside our mixins folder, I'm going to create a new file which is called underscore hotel dot pug and this is going to be the file for our mixin. I know we'd like to start a mixin name with a underscore but this is totally up to you. We begin by using the mixin keyword followed by a name we want to give to this mixin. Mixin hotel then we can go and copy over the hotel code. We already have in our index dot pug. We have this hotel all the way down to our star rating and cost per night. Copy this. Then if we go to our mixin which is underscore hotel. Paste this in and make sure this is indented correctly. One level layer, and then one further level for our image and info. Save this file and that's all we need to do to create our mixin. Now, index dot pug file, we then need to include this mixin file, which we just created. After extends layout. We can also include our mixin by adding the file path. Mixins, which is the folder name, forward slash underscore hotel. We don't need to add the dot pug extension. Then we need to remove the hotel code and then replace it with the name we gave the mixin. Cut or delete this hotel section from the very bottom and then we add our mixin with plus hotel. This hotel name is the name we gave to the mixin inside the file. Underscore hotel dot pug. This is a name which you set right at the top. If we now save this and then over to the index page by clicking on the logo and I scroll down, you can see we have a problem with the indentations. Let's go and check this out and this is an index dot pug, over to our index dot pug, and it looks as though this is not quite lined up with this line. These little small errors are things we need to watch out for with the indentation. Make sure everything works correctly. Let's try reloading this. There's our hotel back in the home page. But this time pulled in from a mixin. Now we can do the same with the all hotels page inside the all hotels dot pug file. We can also include the mixin in the same way as the index. After our extends declaration, we can include our mixin, which again is the file path of mixins, forward slash underscore hotel. Now we can replace this hotel code from dot hotel right down to the cost per night. Then replace this with the mixin using plus hotel. Now we've replaced a section of code from two files and added it into one mixin. We will come back to mixin soon by also passing in data to them about each hotel in the database. Along with also creating more mixins to you, as we go. Our code is now a little shorter now by including this and it will be used a few more times in this project too. Next, we're going to move on to routing and how we can use it to switch between pages in our application. 14. Basic routing: If we go over to Visual Studio Code, and at the moment, if you go inside of the routes folder, and then click on the index.js, we only have one route currently setup, and this is for the homepage. Now we're going to look at how to add more routes too and if routing will allow us to handle what happens when a URL is visited. First, I'm not going to be using the users.js file, which has been included with the express generator. So we can go down and delete users.js, so we can this delete this from our project. Then inside of the app.js, click on the main file here. We also have two references to this user's file, which we can also delete. First of all, we can remove this variable, which points to the user's routes. So delete this, leaving just our main index file. Then a little bit further down, we'll have a app.use which sets we want to use this user's router on the user's file path just here we. So we can also remove this. Now back over to our router index.js file. Let's close down some of these tabs. At the top of this file we have two variables. We have an Express variable and also a route variable here. We have these so we can use the Router functionality which comes with Express. First of all, we require Express, which is a node package and this is inside of the node modules folder. If we require any packages from inside of the node modules, which is just here, we just need to reference it by the module name. If we are requiring any of the file which is not inside the node modules folder, we will need to add the full file path before the name. After setting our Express variable, we then set to open Express router instance, and store it in a router variable. This router variable is also used down here, and also any future routes too. We then use.get here because we are handling a get request. Remember when a user visits any page in the browser, this is a get request. In the last video we added a link to forward slash all. We added this over in our index.pug template, just here. This was to provide a link to all hotels. But we've not handled the route just yet. We go over to index page and select this link. We see we have taken it to forward slash all, but down at the bottom we have a message of Not_Found. We see all the header content just a little still because this content has been added to main layout file. So now we can go ahead and write our own route to handle the forward slash all hotels routes. So back in the index.js, where we're going to be handling all of our routes, we can start just like above with router and this is a get request so we use.get. Inside here, we want this to apply to the forward slash all routes, and other function as the second parameter. So function which takes in the request, and also the response objects. These two variable names can be anything which you prefer. Then open up the curly braces and add a semicolon at the end. Request is an object containing all the information from the HTTP request. As an example, we'll use this soon to access data from within a form, which is passed along with the request. Response, on the other hand, is what we want to send back when we get a request. So request is the data coming into the server, and then response is a response from the server. If you take a look above out-of-home routes, We have res.render a page template as a response from the server. We also looked at res.send earlier too. Here we can also render our all hotels template which we created just here. So inside of router.gets/all we can say, res.render, pass in our templates of all_hotels. Then as an object, we can pass in our title of all hotels. The semicolon at the end here. Now we can test this by going over to the browser, hit "Save", and then refresh. Make sure you only foward/all routes and then scroll down to the bottom. Now we can see this hotel, which we added as a mix in in the last video. Let's also test this once more by going over to the homepage, by clicking on the "Logo", clicking on "See All", and once again we can see this is still working. So now we have two routes in place. One for all hotels and one for the homepage. This is a basic introduction to handling routes with Express. In the next video we'll look at passing data for the URL, when we covert routes parameters. 15. Route parameters: One of the things we have to deal with when routing is that we don't always know what the exact URL will be. What I mean is if we imagine a user's route, each user has a unique user ID. This could be something such as our localhost or our website URL, forward slash users. Then forward slash a username, which could be pretty much anything. This user section that we have just here, probably won't be known in advance to the developer. This section is something which we need to handle beforehand. For this, we can use route parameters to create a dynamic segments in the URL. If we go over to the index.js, which handles all of our routes, let's start by duplicating our forward slash all routes in the last video. Copy this section and then add it in just below. We can then tell express router which parts of the URL we want to be dynamic. After forward slash all, we can then go ahead and add forward slash and then create a dynamic segments using a colon. Then a name we want to give to this section. This name can be anything of our choosing. Then inside of our function just below, we can then access the name data from our URL. We use the request object. Remember we said that this holds information from the HTTP requests. First of all, we can access the request objects, then.params to access the data in the URL parameters, followed by this name variable were added after the colon. So request.params.name. Then if we saw this inside of a constance, so const name is equal to our parameters. This data can also be passed to the templates to use along with the page title. After the title of all hotels, add a comma. Then we can also pass in this name data. This name data is passed to the all hotels templates along with this name. So click on our all hotels.pug file. Then this variable can easily be accessed in the template just by referencing the name. Down at the bottom of the file, p equals our name variable. Then over to the browser. Now if we go to forward slash users and then forward slash, we can add any name into here, hit enter. In fact, this was all an increase and hit enter. Down at the bottom we now see I would name of Chris, which we passed in. We can try this again with anything we want to add. This data is then grabbed from our URL, stored inside the request.params objects. Then we can pass is now down to our template to use in any way which we choose. We can also add as many dynamic segments as we need in the URL. Rather than just having one in index.js, just like this. We can also add this dynamic segment into any section we wanted. We could also grab the age and store it in an age variable. But this all depends on what type of website you are creating. Another thing we can also do if we don't want to grab the data inside of the routes, we can also just add a star. Just like this, we could add a star and then this route, just here, all this function will then run every time a route follows this forward slash all, and then forward slash any data after this. This star can be placed in any section of the URL which you want. This will be useful for handling our user names, even if we didn't want to grab the actual data and store it in a variable. I'm now going to remove this code from the video. Inside of all routes, let's remove the router.get section, as we don't need this for this project. Then all hotels.pug, all we need to remove is p equals name, and restore this box how it was. But we'll come back to route parameters quite a bit later on in this project, where we'll be passing in any hotel IDs along with booking information. 16. MVC Pattern: We're going to be structuring this project using what is known as the MVC pattern. MVC stands for Model View Controller and it's basically a way of separating our logic into different parts. At the top of the diagram here we see the model, the model defines how our data should be structured. As an example, our hotel information will have a model and this model will stay at that each hotel needs to have a name. It's name must be present, and also a string which no longer referred to coat Islam. Also our hotel model must have a description, an image, a price, and so on. Next up and probably the most easy to grasp is the view. The view, which as it sounds is basically the user interface. We've already touched on this in the section where we've created a page templates so this should be fairly straightforward. Then there is the controller. This controller can update the view or send data to the model. A typical use for a controller in our project will be to search our hotel model for matches based on a country, then it's data can then be passed to the template or to the view. We've actually already done something similar in the last video, where we looked at route parameters. Instead of the routes index or js file, we use a controller to get the name from the URL, then we passed this name to the view to show on the homepage. We'll also be using the controller to do other things too, such as form validation when a user signs up before we push this data to the users model. This is a pattern which will be following for the rest of these projects. It's keeping nicely structured and organized. It may seem a little confusing to begin but we will get lots of practice and it will soon become clear. In the next video, we're going to be starting this separation process by creating our controllers. 17. Using controllers: At the moment we are handling overall logic inside of this routers index.js file. We navigate into a certain route and then all the logic is handled inside of this function and also this one which is below. This works fine for small applications, but we will soon outgrow this type of setup. I'm going to separate this logic inside and create a controllers folder in the root of all projects. Let's go over to the sidebar and create a new folder called controllers. Make sure this is at the same level as all level folders, such as the bin and the node modules. Inside here we can add a new JavaScript file for each controller which you want to create. Let's click on controllers and then create a new file. I'm going to create separate controller for the hotel related logic. Then one later on for the users to keep things organized. Let's begin by creating hotel controller.js. Controller with a capital C and then hit "Enter." This file will be a series of functions and we'll basically be outsourcing this function section from our router. We're going to take this logic, put it into our controller, and then it references inside of our router. Let's begin in our hotel controller.js and begin with A exports. This will allow this code to be available in other parts of our application. We then give this exported function a name of our choice. Try to keep it descriptive though so we know what each one will be doing. Let's call this the homepage, and then set this to a function. This is a function which takes in the request and response objects. Let's add these in, so we have full access to them inside of our function. Then if we go over to our index.js, we can then cut out the res.render from our home routes and then add it to our controller and now would also be a good time to change the page title. Let's set this to "Let's travel." We now have our logic separated, so we can now go over to our routers index.js file. We can remove this function leaving in just the initial routes and then we need to reference our host cell controller.homepage. Let's add hotel controller.homepage and then give that a save. If we now go over to the browser and then hit "Reload," and go to the homepage, we now see a message saying the site can't be reached. If we go to Visual Studio and then open up the terminal, we can see that the app has crushed. This is because we need to require this hotel controller file before we can access it. Currently, we're trying to access the hotel controller, but we've not yet imported this file. To do this, let's go to the top of our file and then we can add a comment. So require controllers and then set up a constant, so const hotel controller, which matches this name just here and then we can require the file. We need to add the file path because this is not inside of the node modules folder. This is inside of the controllers folder. So controllers, forward slash hotel controller and now hit "Save." We should now see the app has reloaded. We now have the green text. Over to the browser, and the app is now working in once more. Then we can do the same with the all hotels route too. First, let's go over to the hotel controller and create this. So just like before, we can say exports.listallhotels. Except the E function which takes in the request, the response and then over to a router. We can take the res.render from these, forward slash all. Paste this in, and then references function inside of our router. So remove the function from before. Again, we want the hotel controller file. But this time we want list all hotels. Now, let's try this router on the browser. So the home route forward slash all, scroll down and this still works to. So at the moment we've not gained a lot by having separate controllers. But these controllers will soon become more complex. Especially when we start dealing with databases and obtain the views, along with checking any user data for validation. It makes sense to start separating things from the start, so things don't get too messy as our project grows. 18. Using middleware: Middleware is a really important concept to learn, and it is used quite heavily when building Express apps. While we will be using middleware for his projects, I just wanted to give you a quick introduction first, so we at least understand the basics. If we go over to Visual Studio then open up our hotel controller, we have the request and response objects for each router. Request is the data coming in and response is the data which is returned from the server. We can use middleware in-between to basically change our data or do something with it. Basically, a middleware acts like a series of functions which we pass through. An example of its use in our project, will be when a user signs up. Inside this hotelController.js file, I want to show you a quick example and these examples are just for demonstration purposes. You don't need to follow along if you don't want. Let's make some more space and I'm going to create two more functions. Exports, sign-up, passing in the request and response objects. The sign-up section is going to handle the data validation. This will validate any user info as it comes in then this second one is going to be the functionality to login. Exports.login, passing your request and response and this is going to handle the login. Let's say we want to have the functionality to first sign up the user. The sign-up section also validates the user details then follows up by login, the user in. This is usually the functionality we want. When we sign up for new websites, we often want to be immediately logged in. All of the code to handle both of these sections could be done inside of one single controller. But for this case, it makes sense to break things up into separate actions. This is because not only do we want to sign up and then login straight away, we also want the functionality for this login to be separate. Just when a user has returned and then just wants to login. Let's avoid repeating the same login code more than once. How does Express know we want to run the sign-up function then followed by the login? First of all, we need to pass in a third argument to our function. We usually call this variable next, with their needs call next inside of our function body, when we are ready to move on to the next piece of middleware, so we call next inside here. When we want it to move down the chain onto the next piece of middleware. There is still one more thing to do. Although we call next inside this function, it doesn't automatically know what the next piece of middleware is. All that we know we want to move on to login, Express doesn't know this by default. We do this by declaring the order of middleware inside the router file over to the router index.js. We can then set up a new example routes, we've router.gets. Let's create a sign-up routes with the forward slash and then we can add our controllers. The hotelController.sign-Up. If you just wanted to use this sign-up section, we would just use a like this. We can add more than one. We can then follow up with hotelController.login, and we can pass in as many of these as you want to use and then these executed in sequence, each one requiring the next call inside the function. First of all, we will use the sign-up function, then next we'll pass it over to the login function and since these are now separate functions, this makes sense when we want to create a route just for login into. If we have, router.gets, when we get to this stage, we also want a login routes and then we can reuse hotelController.login. Now we're using the same login functionality without repeating the same code in multiple functions. We can see this is working by adding some console logs to all middleware over to the controller, just before next we can do a console log, and then a simple message of sign-up middleware, lowercase c, then copy this then add this into our login. Changes to be login middleware, save our files and and over to the projects. We need to go to our up routes, which we set just here. Forward slash sign-up, at this end then hit enter. Now only sign-up routes over to the console and make some more space. We now see inside the console at the bottom we have sign-up middleware called first, which you'd expect because this is called first and the controller then we have the login middleware just afterwards. This means that the router is now passing through both pieces of our middleware in the correct sequence. If we go ahead though, and comments sound is next function, save the file then reload the browser on the sign-up routes. Over in a terminal we now see that only the sign-up middleware has run. The code has got to this section just here then it hasn't been passed to the next piece of middleware because we haven't called next. This is a basic introduction to how middleware works. I'm going to remove these two functions as we don't need these in our projects. They just for demonstration and also the two new routes to set-up in the index.js and then check this working okay. Head to the home routes and we're now back to normal. We can load these routes in later on when we come back to this part of the app. Finally, we can also set a middleware to use across the whole site, rather than just one specific route over in the app.js, which is the main file. Click on this then scroll down to the section with app.use, which is just here. Here you can see app.use, and this is where we can set up any middleware such as cookie parser to use for all routes. Below we can see we have the index router setup here too. Both for this and all of the middleware, we can first add a route as the first argument to restrict the middleware to only apply to this particular routes. There is also many of the uses for middleware too, such as third party plugins and we will look at these more throughout this project. 19. Important Update: mLab now part of Mongo: As we progress through the following project, we use a hosted database on a service called mLab. MLab is a fully managed Cloud database service which we use to host our Mongo database. As we can see on the homepage here, mLab has since being acquired by Mongo itself. So we now need to use this service in its place. The service is called Mongo Atlas and it's a pretty straightforward swap since we just set up a database in a similar way and then use the connection string provided in our projects. Mongo Atlas is also free to sign up for and it has a free tier for development too. So let's start by going over to mongodb.com/cloud/atlas. If you've used Atlas before and already have an account, you can go ahead and login. If not, you'll need to register first before we can create our first database cluster. So if you need to go ahead and sign up, but I'm going to go down and login to Atlas now. Then once you're all setup and registered, we need to go ahead and create a new cluster. Create a new cluster may pop up as part of the registration process. So let's go ahead and build a new cluster which is going to allow us to select our region or our plan. There is some pre-configured options and you can leave the defaults as they are or change to your closest region. So I'm going to select the closest regions me. Also keep an eye out for the free tier label, which isn't in each one. Everything else, I'm going to keep us default. Just make sure you see the cost down at the bottom to be free. Then we can go ahead and create our cluster by clicking on the green button. A new cluster can take a few minutes to get set up. So I'm going to go away now and come back as soon as this is all done. So this is my cluster all now setup and the next step is to create a new user. If we go to the security tab and then go to add new user, this user is going to be for ourselves. So we can select the atlas Admin, which is one of the options on the privileges. You can of course add more users with different permissions at a later date if you need to. Then add a username and password of your choice. I'm going to add a username and a password and then go ahead and add our user. The next step is to add our own computers' IP address to Mongo's whitelist. This is a security feature so only our machine is granted permission to access our cluster. You may need to bear this in mind at a later stage when deploying the application to other services. So let's go on to the Security tab and click on 'IP whitelist'. Add IP address. We get a pop-up and we can confirm that we want to use our current IP address by clicking this button here. Then we'll get the IP address added and this field follows. So we can just go ahead and confirm. You may need to give this a few moments to get setup if you see this pending spinner just here. If you've not used Mongo Atlas before, we can check the contents of our database by clicking on the collections button. The collections button is in the overview tab and then collections. This gives us access to all of the collections which our database has and we can interact with our data. Add new fields, add new collections and see all the information which is stored in our database. Of course, we don't have any data just yet, but this is where you can access all of our database information, such as any hotels and users, which we'll go ahead and save from our project. Finally, we need a connection string. If we go to overview and then click on 'Connect'. The option we want to use is connect your application. There is also options here to use MongoDB Compass and also connect with the Mongo Shell. Both connect your application is the one we need for now. We also need to change the driver version to be version two. Then we see our connection string is displayed just here and we can also copy this to the clipboard. This connection string is the one which we'll use in our project in place of the one provided by mLab. This is done for this update. Just keep this open in the browser and you can use it in the next video when we connect to our database. Also just bear in mind as you go through the course, you will need to go through these Mongo Atlas surveys to see your data rather than mLab as I occasionally do in the class. All you need to do to see this is click on the collections button us we looked at before. 20. Getting started with Mongo: In this project, we're going to be dealing with quite a bit of information. We'll have information about how hotels we have and uses any orders which you placed and also any session data which we'll get into later. Of course, so we need somewhere to store all of this data, and I'm going to be using a MongoDB database, in this course, which is really popular database for Node applications, along with many of this too. MongoDB allows us to store our data in a JSON-like format. This makes it really easy to work with, especially when we used to JavaScript type applications. We've already worked with JSON data, so this should be fairly familiar. It also makes learning things easier too. There's also lots of helpful queries which it makes available. The query is a search on our database, and Mongo makes this really easy. We have lots of different ways we can perform searches to only get the exact data we need. For example, one of the queries which we'll be using is to search the database using a search term which they use Enter and then also filtered out by the star rating and availability, and then finally sought the results in price order. We'll also look at lots of queries too unit section. MongoDB is also free and open source too. I will also be using a hosted version in this course, which is also free. The hosted version is going to be over mLab, which you can find our mLab.com. This hosted solution is also known as a database, as a service. It basically allows us to quickly get going with MongoDB. Our database is then hosted in the cloud photos. You can also set Mongo up locally, we have in our database already hosted is really useful for later when we push our application to be live server. It also saves the configuration. The first thing we need to do is sign up for a user accounts, so if you don't already have an account with mLab, I would suggest you go ahead and pause the video and then sign-up now. I already have an account with mLab, so I'm going to go ahead and login, so add in the login details. Once we're logged in, we can now go ahead and create a new MongoDB deployments. Go to the top, and click create new, then we have some options to select, I'll be using Amazon for the provider, so click on this, and then the free sandbox plan, which is fine for development and learning. Select this and select a region. Amazon is hosted in multiple locations across the world, we only have a few options for is sandbox plan, so AWS will be fine. We can continue, and we can select one of these. Then continue again, and then we can add our database name. I'm going to call mine, let's-travel. Continue. We can review any of this and then hit Submit Order, and there we go that's our let's-travel database on our setup. Our database is empty, so it doesn't have any collections. Just gets, if we click on this, we can then take a look inside. Under the Collection Tab we see we don't have any at this time, and the collection is just a way of grouping our documents, which we store, as an example, we have a hotel's collection to store our hotel records, a user's collection, to store assigned abuses and so on. The top, we also have a URI which we can use in our project to connect to this database. There is a space in this URI for our user and also a password, so we need to go ahead and set this up under the user's tab. Click on this and then go to Add database user. We can add a username and password, so I'm going to just call mine travel as username, and traveled on as the password. Create our user, great. Now have the username and password to fill in these blanks. But first there is one more thing which needs setup, and this is mongoose. js. We are free to use Mongo directly if you want, but I'm going to be using a nose package called Mongoose instead. Mongoose basically allows us to give our data some structure in which is called a schema. If we write directly to Mongo, you can make a mistake pretty easily. If we do not set up how our data should be, Mongoose will allow us to set how our data would look. For example, will have a hotel schema, and this will have fields such as a name and description. We can now answer the datatype, each field should be, such as a string, and also restrict the minimum and maximum characters it should be, and also if the field is to be required and so on. Basically it stops us from doing things such as entry and a text string into a price field, which should be a number. This package will also allow us to create our model, which is the model we talked about when we looked at the MVC pattern, given our data some consistency. Let's go ahead and install Mongoose in our application. Let's close the terminal down with Control C. Then type in npm i mongoose. Notice this time using the shorter i command, this is just a shorthand for install and if works fine. Hit "Enter" give it some moment to pull-in from mpm. I'm checking whether this is all okay by opening up our package.json, and in the dependencies will now see we have Mongoose listed here. Over a in our app.js, we can now set up our connection. Again in the sidebar we can open up app.js. Then close this, so the first thing we need to do is to setup our connection. We need to first require the Mongoose package, which we just imported. Just after our import, I'm going to use a constant, and it doesn't matter if you use a constant or a variable, but I'm going to use the constants from now on, so const Mongoose equals require Mongoose, and remember if we're requiring a package from the node modules folder, we just simply reference it by the package name rather than adding a file path which leads to it. Then we can set up our connection using the connect method, so that's first access Mongoose. Scroll down on the app.set. Let's setup our Mongoose connection, so Mongoose variable.connect and then open up the brackets. Inside of connect, we can pass in our connection URI from mLab,so back out to mLab, copy the full URI, and as a string, open the quotations and then paste this in. Rather, we need to change our username and password, so remove the user and our username was travel and the password was travel on. Of course, when dealing with databases, you want a more secure password, but this is just for demonstration. Also have NSURI in here is not the best way to do this, but we'll move this to somewhere more suitable later. On the next line on the Mongoose. connect, we need to set Mongoose. Promise, P, this is going to be equal to the global.Promise, P again. Once we start to query our database, we need to deal with the information which is returned back to us. In earlier versions of Mongoose, we used a callback based setup, but now we can make use of promises which are lot simpler and easier to maintain. We can set Mongo to use the Promise library such as blueband, if we wanted to, which we can get as an NPM module, or I'm going to set it to be the global. Promise you have here, which allows us to make use of the native Promises available in ES6 rather than installing another node module. Next, under this, we can check for any connection errors. We first check, we have a Mongoose connection, and then once we do, we can call.on,.on is a node method which adds an event listener. In our case, we want to list now for any errors, so compositing error as the first parameter, and then as a second argument, passing a callback function to display this error. Let's create a function where we're passing error, which is going to output any error messages to the web console. We do this wave console.error, and can passing this error.message. Pass our message to the console, so let's give this a safe and a semicolon at the ends and then over to the browser or to our index and then reload, and in fact we need to restart our terminal after install Mongoose, so let's go to the terminal and then run npm run devstart, wave it to kick in and then reload the browser and check everything it still works okay. If you don't see any error messages inside of Visual Studio's terminal this should be all now setup. If you have an error do check for any typos and also check that your database URI matches the one on mLab along with the correct user and password, and once this is working and you're stage, you will now good to move on to creating our Mongoose model. 21. Mongoose models: We've already talked a little about what models, we are going to using a Mongoose sets up our models, and this will keep our data structured, so there is less chance of messing up. These models are responsible for creating data before sending off to the database along with written documents from the database too. Over in our project, we can begin by creating a models folder to keep our code organized. Open up the sidebar and then the root of the project, create New Folder called Models. Now we have models and our views, and our controllers folders and this is the MVC pattern we talked about earlier. This model we're creating is going to be for our hotels. This will have the structure for our hotel name, hotel description, star rating, and so on. Inside its models folder, create a New File, call it hotel.js. Since we use mongoose for our schema, we need to require the mongoose module. Let's close on these files down and concentrates on hotel.js. Inside here we create our constant of mongoose and require the mongoose package, semicolon and then we can create our hotel schema, so const hotelSchema, and this is equal to a new mongoose.Schema with a capital S. The Schema will map or match to the data inside of our database, therefore, what we aren't in here will shape how our database data will be constructed. The schema takes in an object inside the brackets, where we can begin to construct how each hotel would look. We need a hotel name, so let's add our first phoneme of hotel_name. Now we can set this up as an object, we want the hotel name to be of type. This is going to be a string separated by commas. We can also add some more restrictions to this data, we can also set if this is to be required, this can be a boolean value of true or false. If the field must be present or instead, we can simply add a string with a message if this field is missing, such as hotel name is required. I come on to the end. Then we can set the maximum number of characters to be 32. Then finally, we're going to set the trim to be a boolean value of true. We'll remove any wide spaces from the field from the beginning and end, leaving just the characters which answers. This is the schema for our hotel name, and we can go ahead and add a similar setup for our description. Separated by a comma, we can ask the hotel_description. The description again should be type of string required. Again, we can set this to be true or instead we can pass in a string which will be returned if the field is missing, so hotel description is required. We can also trim any wide space, set this to be true. Now we have the hotel name and the description, separate this with a comma, we now have a field for the image. The image is going to be a name, so it's going to be a string for now, we will come back to this image later on in the course because it's one or two things we need to deal with to get this working correctly. Next up we have the star rating, the star rating is going to be a type of number. We also want this to be required like all the rest of the fields. We can say hotel star rating is required, add a common onto the ends. Then we set the maximum value to be five, because we only want the star rating to between one and five. After the star rating, it's the country, the country is a type of string. This is also required, the text of country is required, the comma after required. We also want to finish, so this is a boolean value of true. That's all we need at the moment for our country. After the country, we want to set the cost per night. Cost per night is going to be the type of number, as this will be a price, and also want this to be required. With a string of cost per night, is required. The last piece of information we want to store in our hotel model is available. This is so the unmanned concise if this Hotel is currently available for sale and this will be a boolean value of true or false. Let's set the type to be boolean and the only other field we need is required, so availability is required. Once you've gone ahead and typed all this out, right at the very bottom. The final thing we want to do is export our model so we can use it in other files. Down at the bottom must create a comment of export model. We do this with module dot exports, answer this to mongoose.model, the first volume we want to add is hotel. Hotel is a name I'm going to give to this model and separated by a comma, we also pass in the hotel schema, which we just created. Good, this is now how our hotel would be constructed. Now we've setup our model. It means nobody could just go ahead and add any fields how they like. We now have a strict set of rules which each hotel must abide by. Later we'll add another model for our user too and also for any orders. We can also shape how they will look too. For now though, we're going to stick with the hotels. The next video is all about using this model to create our add new hotel phone, so we can adds new hotels to our database. 22. Creating our hotel upload form: Before we can push new hotels to the database, we need to create a HTML form, so we can add the details we want to enter. This formal parts of our admin section. So let's add this admin route first over in the index.js. Open the sidebar, into the routes, and then index.js. I'm going to go down to the bottom of our router just for the export. Let's make a comment, and I will say "ADMIN Routes". The first one we're going to use is router.get, since this is a GET request. We want this to be for the forward slash admin routes. Then we want to run our hotelController, I'm going to call it call it the adminPage, semicolon at the end. As we can see with the red area down at the bottom, we don't yet have this adminPage in the control yet, so this should be next. Open the sidebar and go to our hotelController.js file, and then we can add this right at the bottom. Exports towards adminPage, it's going to be equal to our function, which takes in the request and response objects. Then inside the function body, what we're going to do is a res.render, this is going to render an admin template, and then take in an options object where we will pass in the title like we've done previously. The title can simply be Admin, and then add a semicolon at the end. Now for the admin.book file to display this. Let's go and create this admin template, open up the sidebar, into our views folder, create a new file called admin with the dot pug extension. This admin route is going to be fairly simple. At the moment all we're going to do is pass in the title and then create a unordered list. This is going to have some links for the admin to use, such as the links to our new hotel, to edit or remove hotels, and to see any bookings which has been made. Let's extend our layout. Extends layout at the very top, and then replace the content block. Indent it one level we can pass in our h2, which is the title. Then want to separate this title with the links with the horizontal line. These three links are going to be an unordered list. The first list item, nested inside we can add a a for a link with the href equal to forward slash admin, and then forward slash add. This is going to be the route which is going to handle the add in new hotels to the database. The texts of Add new hotel. Then we'll do this two more times. Our second list item is also a link. This href is going to go to forward slash admin and then forward slash edit dash remove. The text of Edit forward slash Remove Hotel. We'll come back to this one later on when we look at editing and removing hotels. The third one again is going to be for later too and this is going to be a link which is going to link to a route which is forward slash admin forward slash orders. The text of View bookings and give that a save. You can test if it's working by going over to the browser and then checking out the forward slash admin routes, and then hit and enter. If we scroll down, we have our title of Admin, which is passed to the templates and then our three links which we just created. If we go ahead and click on "Add new hotel" at the top, we're taken to forward slash admin forward slash add, which was set up just here. This results in an error down at the bottom because we also need to set up this route too, along with a page template. Back over to our router file, which is index.js. Let's set this up with router.get. This router was forward slash admin, forward slash add, to add a new hotel, and then setup our hotelController, and the function name of createHotelGet with a semicolon at the end. You may be wondering why we've called this createHotelGet, rather than simply create hotel. I've added Get onto the end because this is a GET request. Later will also be creating a POST request to this create hotel route. It makes it more clear when we get to that stage. This is now our route. We can now move on to the controller to render our view. Let's click on "hotelController.js" down at the bottom. Let's set this up. It was exports.createHotelGet sets up our function with the request and response objects. This is going to simply render a view. We do this with res.render, just like we did with the adminPage. The template we're going to create is going to be add underscore hotel, and then pass in the objects, which sends the title of Add new hotel and a semicolon at the end. Just like we this admin two we've not yet created this add hotel page. Go to the sidebar, go to the views, and create a new file, called add underscore hotel with the dot plug extension. Now it's a case of making this a form, which is going to be used to submit the hotel to our database. This needs to extend our layout, select all of the files, and then block content. Just before we get to adding our form, I'm going to add a link at the top of the page. This link is going to link back to the admin section, so we can quickly switch between the add new hotel and then go back to our three main links. The link with the href equals forward slash admin. This is going to be a button. We can add a button type. So type equals button. Then we'll also add a class which we are going to be using later when we add some CSS or button underscore small. The text goes back to admin as this is where this is linking to. Then at the very bottom we pass in our page title. To keep this consistent we'll add this in a h2. So h2 equals title. Give this a save and check if it's working. Refresh forward slash admin, forward slash add. Underneath the layer so we can now see our button of back to admin, click on this and then we're taken back to our three links. We can now go back to add new hotel. We need create our form now which is going to have all the fields we need for our hotel. These fields need so much of the data inside our model. Let's go ahead and create our form underneath the h2. The form and then the attributes inside the brackets, the action. This is going to link to the same page, so we can keep the routes with an empty string. The method, this is going to be a post request. Then indent it in one level. I'm going to create a div which is going to have the class of form underscore input. Each one of these form groups is going to have the same class. We can keep the styling consistent when we get to the CSS later. The first one will be labeled and this is going to be for hotel name. So hotel underscore name, and then the text of Hotel name. After the label will then add our input. This input is going to have the type of text, the name of hotel_name. Like I mentioned before, these fields need to match the data in our model. If we go over to our hotel.js and we'll begin right at the top with hotel name. This needs much name, which we gave this in our schema. Hotel_name. Then we'll do the same for description and also for the rest of the fields inside here. Back to our form. The name of hotel name and this field is also required. The next one is going to be for the description. The surrounding div of form input, the label. This one is going to be for hotel description. Then it's x-naught hotel description. This time rather than an input, this is going to be a text area. We do this input, just like the rest of the elements. We can add the name of texts area, and then we add the brackets or the attributes. The name of hotel_description. The ID, which is also hotel_description and let's make this smaller so it all fits on one line with the text area. You can also set the default number of columns and also rows. So I'm going to set the columns to be 13 and also the rows to be ten. This is also required too, like all the rest of the fields. Below this thing,next one is going to be for the hotel image. So I'm going to go ahead and add the wrapper which is form inputs, the label for the image, the textile photo image. This time it's going to be an input for the file. So the inputs with the type of file, since we'll be using uploaded images from the user machine. So the type of file, the name is going to be image along with the ID. Let's go ahead and copy this hotel name. Then after the image paces in, this one is going to be for the star rating. So the label will have the name of star_rating and this will be a star rating of one to five. Star rating for the name is input type is going to be of number. To restrict this from one to five with the name of star_rating. This is also required to. Let's Keep this between one and five. We can also add the min attributes of one and also the maximum attributes of five. Go to under the star rating, we can add this in again, make sure the indentation is correct. This one after the star rating is going to be for the country. So the name of country, the same for the text. The input type is also going to be text too. So we can name this the name of country and also let's give this an ID of country too. This is also required too. The same again after the country. This one is going to be for the cost per night. So the label is going to be for cost_per_night. Text of cost per night to, the inputs is going to be for price. So we can set this to be a number. The name can also match this, so we can copy this and paste this in for the inputs. So we have the type, the name, and we also need the ID of cost per night too. So add this in and the next one after this, if we go right down to the very bottom, is going to be for the availability. So we're going to add some radio buttons. Which we can select if the hotel is available or unavailable. So the wrapper of form inputs is going to have two radio buttons. The first one can have a label and this is for available, the text is available too. Then our input, which is the type of radio. After the type we can add the ID and this one is going to be the same. This also needs a name. This is the time of available. This is the data which we sent to the server. The value is going to be equal to true and we'll set the next one to be equal to false. So if this one is checked, we'll get the available equal to true, and the next one will be available equal to false. By default, we want this true to be checked. So we can also add the checked attribute inside there. Then we just need to do the same for unavailable so we can copy these two lines and then add them below. This is unavailable as is the text and then the input. We can add on, save the name, the value of false. We can also remove this checked attribute because we only want one checked at once. So now the last thing we need to do is a button which is going to go ahead and submit this form. This can have the same form input wrapper. Skip the styling consistent. This time this is a button with the type of submit, the class, the class we've already used before of button_small. This will keep the CSS more consistent and then in capital we're also going to add the button text of Confirm. We can now save this and then go over to our admin. Make sure we're on forward/admin,forward /ads. Now we should see the add new hotel form down at the bottom. If you've seen your form with no errors, congratulations. If you do see any errors, make sure you check over your code for any typos. Before moving on to the next video, we will finally get a hotel push to our database 23. Pushing to the database: We all now set to get to work pushing the hotel data to our Mongo database. In the last video, we created a template called Art_hotel. This form is setup to make a post request. If you go to the top, we can see the method is set to post. This will post our form data so we can go ahead and use it in our controller. Also, the action is set to an empty string, which we can see just here. This will post the form data to the current routes, which is forward/admin, forward/add. If we go over to our routes and enter the index.js, we already have a get request on this forward/add route just here to display our at new hotel form. So let's duplicate this line to create a post request. So copy this and paste this below. We need this to be a post request as we're dealing with a post request from our form. So router.post, again we can keep this one as forward/admin, forward/add because this is the file path which we're going to be posting to, since we've not set our y's in our action. So since this is a post request, we can change create hotel post, and this create hotel post middle-ware will handle what to do when we make a post request to this route, i.e. when we submit the form. Let's set this up in the hotel controller.js under createHotelGet. We can do the same for createHotelPost. So createHotelPost sets up our function with the request and response. The first thing I'm going to do inside here is to see what data we're working with. We can see what data is being sent by the form by using res.json, so I'll put the data as JSON, then pass in the request a body, and this is where the data is stored in our quest objects. So inside of our function at res.json and the form data is stored in the body of the request objects so pass in request.body gives us a save and then over to the browser, get that reload. Now we can fill in some form data to submit. That's just adding a test. That's a test data, choose an image, into our Travel project, and then the public folder, images, and we can choose any hotel image. So I'm going to select Hotel 1, a star rating of three, country, Portugal and any price is fine. We confirm, so as soon as we hit Confirm, we then make a post request from this form. This post request is going to forward/Admin, forward/add. We set this up inside of our index.js to handle this post request to this route. This is then triggering our hotel controller, which is then returning our JSON since we are doing res.json and then passed in the request.body, which stores the data being sent by the form. So now we can see the JSON version of our hotel which we just added. We can see this data is setup in the same format as our model. This gives us a better idea of the data we're now working with. This form has been set up to be the same as our model so the data is in the correct format. Now we know we have an object for our hotel stored in request.body. Will we use this data in our model to push to the database? So we need to require our hotel model first, the top level file. So back to the hotel controller, and at the very top, we can set up a constant called Hotel with capital H, and this will require the models. So as a string when it's passing the file path, so let's go up to our model's folder, and then the name of the model was Hotel. We can then use this Hotel model down in createHotelPost. So we're going to set up a new Hotel, pass in the data from request.body, which we've seen is the object which contains all the fields from our form. They install is inside of a variable or a constant. So const hotel equals our new Hotel. So now we have our hotel and we can go ahead and call safe. But one thing first, I'm going to mark this function as async. Just after the equals, we can mark this function as an async function. This is something which is new in ES 2017 called async await. It really does make our lives a lot easier when working with asynchronous code. What it basically allows us to do is to pause a function until a line of code has finished running. First of all, we mark the function async, just like we did there, and then the next task our function has, is to call save to say this to our database. We do this with our hotel constant and then call.save. With the save, however, we want to make sure the hotel has finished saving before we can start doing things with it. To do this, we can add a wait before our hotel.save, adding a wait before this line. We'll make sure this code pauses and then wait for this to finish before moving on to the next line. The reason why we want to make sure we await the hotel saving before moving on is because we will assume new this hotel data immediately after the save. So we want to make sure that the save has completed, it's available before calling any more lines of code which need this hotel data. So if we give this to save and then over to the browser, gives this a reload and resubmit the form, and then go back over to mLab and login to database. So let's add in our user details. Once our database loads up, we can now see on Java collections we have the hotel collection, which now has one documents. If we click on next to expand, we're then taken to our test, which is the data which we just submitted. This is a big step because we've now saved our hotel to the database. But what if there is an error when saving the hotel? We need to add something inside of our controller to handle any errors. First, we can wrap the code inside the try block. So back to createHotelPost, we can add try and then move these two lines inside of this try block. This will try to run the code inside and test for any errors. If there are any errors, we can handle them with a catch statements. We do this at the end, we catch, we pass in the error, and then inside here we call next, which also takes in the error. Calling next, I'm passing in the era, will pass the error along the middle-ware chain until it reaches an error handler which can deal with it correctly. Remember, we already have error handlers setup with the express framework inside of our app.js, which is down at the bottom here. So back to our controller for this next to work correctly, we also need to pass in next after the request and response objects. So passing next here since we're now using it inside of our function. If we head over to mLab, inside the browser, we can look at our hotel. If we click on this corner and then drag this down. If we notice, inside of this hotel which we just added, there's been a unique ID added with the field of underscore ID, which is just here. Remember from before, we said we wanted to use await to wait on the hotel saving this database before moving on. Making sure the hotel has successfully saved means we now have this ID available before move on to the next line of code. This only because I now want to redirect to the hotel once it's been saved. We can do this inside of our controller with res.redirect. Then passing the file path we want to go to, I'm going to use the back ticks since we're going to add some dynamic data. So forward/all, and then forward/. We can pass in the $ symbol and our curly braces. This is something we looked at early on in the JavaScript section. So inside here we can pass in a variable. So we can access our hotel object, which is just here, and then the field which is underscore ID, and this is the idea which had been added inside of our database just here. Add a semicolon at the end. Now let's check this is working okay by adding a new hotel. So let's go to forward/Admin forward/add, reload the page. Let's say test 2. Test 2 for the description, any image is five here. Then click Confirm. We're now redirected to our route, which we set just here, which will be foward/all, and then the hotel ID. We can now see this in the URL bar at the top. We have our unique ID, which is now pulled in from the database because we waited on this hotel to be created first before moving on to the redirect. If we scroll down, we see an error of Not Found. This is fine because we know we have not created this route yet, but the main thing is we have this unique ID now any in the URL. We'll come back to this later when we create a template to display the full hotel detail. This is a big step forward now, we saved into the database. So congratulations, if you now have this working. If you don't, make sure to check over your code and take a look at the finished code provided or ask in the Q&A sections before moving on to the next video. 24. Querying the database: Before we look at how to get our data from the database or from a query, we first need to add some more data to get back. If you go over to mLab and if you have any this test data coming in place, we can remove it with the bin icon on the right-hand side. I want to clear all of the records in our database and make sure they're all gone. Let's go ahead and create five new hotels to work with. We can do this if we go to admin, so vote/admin/vote/add and then go down to [inaudible] at the bottom. The first one I want to call this Hotel 1 and of course with a more creative name if you prefer. I'm going to grab some [inaudible] Ipsum texts to add for the description. Let's go down and create two paragraphs. It generates, Copy the sample text and Paste it in to our text area. The hotel image for Hotel 1 then select this. The star rating can be four, country Jamaica. Cost per night, now we can leave this as available. Now we redirect it to the hotel. We need to go back to our admin/add. Create Hotel 2. Paste in the description the image for Hotel 2. Then a star rating will go for five, country of Dominican Republic. Costs per night, add something there and confirm. It should be two hotels now in our database if we hit Reload, and there we are. Let's add three more. Again, /admin/adds. We can add hotel number three, adds the description hotel3.jpg. A star rating we go for three this time and Netherlands. Cost per night, say 45 and then confirm. Then we can add Hotel 4, admin adds. Then down to the bottom Hotel 4 Paste in the description the image. The star rating will go for five this time and the country of the Maldives. Cost per night, let's go for 89. Let me some how make this unavailable. It looks like we had a little issue there actually, we have both of these checked. Let's go to our form, add hotel and down to the check boxes or the radio buttons. Sorry. These needs have the same name, them too much in the same group, let's try reload in. Yet now we can just select one of these. Let's go over to the database. Now, we have all these available as true. I'm just going to go into any of these and click on the edit button. We'll set the availability this time to be false. It's Save and go back. Because now I have hotel number three to be set to false. Let's add one more which is Hotel 5. The description Hotel 5 image. The star rating let go for two this time. The country of Greece, cost per night and we can keep this one as available. Now, over in mLab we should now have five records with one of these being unavailable, which are said to be Hotel number three. We'll add the rest of the hotel's later on. But now we have some data to work with. I'm going to show you how to get it into our application inside of the hotelController.js. Let's select this and then we can go back to our list all hotels function. If we scroll up, we have the list all hotels just here. Returning all the data in our database is fairly easy using Mongos find method. Before we render all hotels, let's create a constant called all hotels and I'm going to set this to be await because we want this data to be pulled in before rendering template. We want to select our hotel model and then use the dot find method and a semicolon at the end. The find method will find all documents in our hotel collection and also search the hotel collection because we're using the hotel model just here. Here since we're using await once again, we also need to mark this function as a sync for it to work. Add sync just before our function parameters, we also want to handle any errors again two so we can wrap this code in a try block. Let's cut all these two lines of code, add a try block, paste this back-in, followed by a catch block to handle any errors. This catch block also takes in the errors as an argument and then we can also pass these on to next. Since we now call next, we also need to pass this into the function. Our next as the third arguments and before moving on we should check this is working. We can comment out this res.render that we have above and instead replace it with a res.json. This will add the data to the screen in JSON format. The data want to output is all hotels, which is this constant just here. So save this. Then we need to go over to the browser, and then go to /all hit, "Enter" and now we see all of our hotels in JSON format. This is all the data which we now pull in from the database. This looks like all of our Hotel is being returned. We can see all of our fields including the generated ID. Now, we know this is working we can then pass this data to our page template to go ahead and render. Back over to the controller. Let's comment out the res.json and uncomment out this render method. Along with rendering it, the all hotels templates and passing along the title, we also want to pass in this hotel data of all hotels. Separated by a comma, we can also pass in all hotels and this will now be available to use in the templates. If you give this a save and then go over to the all hotels templates, which is in views. Let's open this up. Let's test this working by selecting p elements and send this to the value of all hotels. Give that a save. Then over to the browser, we can reload the /all routes. Okay and scroll down. We see one giant object on the screen now. This is all the data which is now pulled in from the database. We can see if we look closely, we have hotel one, and then if we go further across, we have hotel two just here, and then hotel three further down. This is all the information from our hotels collection. We can also filter this down if we just want the first hotel, for example. We could select it by the index number. All hotels, the index number of zero, reload. That's all the data from our first hotel. Even further, we can narrow this down to the hotel name. Remember, hotel name is stored in hotel underscore name, so we can access it using the dot notation, so hotel name. There we go. There's our hotel one name. Now we have access to all this hotel data. We need to live through all hotels and display each one in this hotel mix-in. We already have the hotel mix-in just here. Once you create a loop which displays this mix-in with all the hotel information. Delete this p element from here. We can add our level two heading, which is the title. Then after this, we want to create our loop, and we'll do this with each hotel in all hotels, and then indent both these lines in. All hotels is the data which will be passed to the template with all the information from hotel one through to five. Each individual hotel will be stored in this hotel variable. Now if we save this and then reload the forward slash all routes and then scroll down, we see we have hotel number one. If we keep going down, we should have hotel one for each one of the items in our database. This is now repeated the same hotel in our mix-in for each item. This is a step in the right direction because we now have five items on the screen, but we want each hotel to be different. To do this, we need a way of passing the unique hotel data into the mix-in. Remember we said, before that this hotel variable here holds the individual hotel information, so this is the information which we need to pass to the mix-in. We can do this with our mix-in just here and pass in the hotel. This works because mix-ins are compiled to functions which can take in arguments. If we save this and then go over to our hotel data in our mix-in, down to mix-ins then underscore hotel up to our mix-in name at the top. We can also receive this hotel data, so passing hotel as an argument, and now we have the individual hotel data inside of this mix-in. This is where the good part begins to happen. Let's begin by displaying the hotel name. Scroll down to our level three heading. Here we have some hard-coded text because this is a variable we add to the equals, access the hotel, and then dot hotel underscore name. If we save this and then reload the browser, back up to the top, we have hotel one, hotel two, hotel three, four, and five. Now we see all the hotel names are unique. We can now carry on with the rest of the details making them all dynamic. Next, we can add the data from the two links. The href just up here, let's change this to be back ticks because this will be dynamic. This is going to link to the full hotel view, which is going to be our forward slash all. Then we can add our dynamic section, which is hotel._id. We'll deal with this route later on. We'll also do the same for the link below. Copy this and paste it in for the second link. Having these two links means both the image and also the hotel name will link to the full view of the hotel when the user clicks on either of these. Then we can deal with the file path for the image. At the moment, we just have the image hotel one hard-coded inside here. Let's change this to be back ticks forward slash images, the hotel's folder inside the images, and then forward slash we can open up the curly braces and then add hotel dot image. Inside of our database for the image, these images are saved. If we take a look, for example, image here is saved as hotel2.jpg. If we go over to Visual Studio and then into public and then images inside of the hotels, this name will match the name of the images which we'll have in here. Now if we save this and then reload the browser, we should now see the unique image for each hotel. We'll come back to the images later because we're going to be using Cloud Storage for image uploads rather than storing in our own project. Now let's head back over and finish off the rest of this dynamic data. The p elements are the bottom, but also now going to be dynamic. We need to surround this in back ticks, change the star. Rather than having the hard-coded value of four, we can again pass in our dynamic data. Hotel and then the field name, which is star underscore rating. The same for our country. We can surround this in back ticks, replace the hard-coded country with hotel dot country. The cost per night. First of all, we can add a currency symbol and then a space to create our dynamic data. Hotel.cost_per_night. Let's head over to the browser and see how this looks. Refresh our all hotels routes and check these all difference. We have four, Jamaica, and 67. Then we have the Dominican, Netherlands, and also the Maldives with different star ratings and prices too. Excellent. You should now be seeing all of your hotel data from the database. You may be also wondering where we have the hotel description, well we'll add this back in later because this is only to be displayed on the full hotel detail view where we have more available space. There is one little problem here though. The problem being we can also see hotel three. If we scroll down to hotel three just here, remember we set this hotel three to be unavailable when we first created it. This is pretty easy to resolve. All we need to do rather than just using the find method, we can also pass in a query. Back over to the hotel controller and to list all hotels. Inside of this find method we have here, we can begin by passing in a object, and then we can select the available fields from our database. Now we only want to find hotels which has this field set to true. We can do this with the $ symbol eq and set this to true. $ sign eq is a MongoDB query operator which checks for equality. Basically, only hotels with the field of available will then be returned. Now if we save this and then reload, now hotel four, and then it jumps to hotel two. It looks as though now hotel three is not being pulled in from the database because it doesn't match our query. Good. This is now all working. We're going to continue pulling in data from our database in the next video where we will be getting our hotels based on the country. 25. Distinct values: If we head over to mongodb.com, which is a homepage for our database. Up at the top, we can see a link to the documentation. This documentation is going to give us all the information we need to query our database. On the left-hand side, if we click on getting started. Here, we can find a full reference to all the database commands, which we're use in this course, along with many others. Down at the bottom we have a reference section. Click on this, and then go to database commands. This will give us a list of different methods which we have available. Let's scroll down to the use commands. Underneath here we have a find method. If we scroll down to the query and write operation commands, you have this fine method which we used in the last video to get all of our hotels. The next one which will be covering in this course is distinct and this command is near the top. We have this just here. For this project, we need to get a list of available countries which have hotels located in. We may have multiple hotels with the same query law. For example, we could have six hotels located in Mexico and we don't want the word Mexico to a appear six times in our country's list. Distinct will allow us to return an array of only the distinctive countries, meaning the only Mexico will appear once from our example. Let's begin by creating the all countries templates for this page. Open up the sidebar, let's close off some of these. I close this down. If we go to the views, we can create a new file inside of here called, all_countries with the.pug extension. We go ahead and add our basic code; extends layout, and then the block content, the h2 of title. Then next stop, we can add the route to the index of JS file. Go to our index inside the routes folder, open this up, and then after the " /all route", we're going to add router.get. This you got to handle the /countries routes, the hotelcontroller, and this time we're going to set up a function called listAllcountries, add the semicolon at the end. We have not yet created lists all countries. So, head over to the hotel controller file and then we can add it in. Let's open this up. After a list all hotels let's add exports.listAllcountries. Setup our function. I'm going to mark this as async, because we're going to need an await inside of here. We can pass in our request, our response, and also next. Then add our try block, try and run the code, followed by our catch, which is going to take in any errors and then pass them over to next. Make my error with no s. The code inside of the try block will be fairly similar to the all hotels above. We begin by creating a constant to store our data in. I'm going to call this constant allcountries. This time now we select our hotel model, so set this equal to Hotel capital H. Instead of the find method that we used before, this time we use.distinct then to return an array of distinct countries, we can pass in the country field as a string, and then under this we can render our templates with res.render. The template we want to add is the one that we just created of all underscore countries. Separated by comma we can pass in our title. Way to the text of, browse by country, I make this little bit smaller, then we can pass in our all countries data, which we set up here. Make sure that this is available to use inside of our template. Once this is done, hit save and then go to the browser, open up our projects, then we can go to /countries, and then scroll down, and we'll see the page title of browse by country. We only see this page title, because this is all we have currently setup in the template. Let's go to all countries.pug, and fix this by adding the all countries data. Which we now pass in to the template. I'm going to begin with a wrap if, just like we did with the hotels. This is going to be called country wrapper, then create an unordered list to display the list of all countries. To get all of these countries, we need to loop through this all countries data, which will pass to this template. We can do this with a loop, so each country in all countries, create a list item, which is also going to be a link. Pass in the href. This is going to be equal to our back takes, and then /countries/, then we can add our dynamic country name. So these are the country inside here, which is this individual variable that we loop through. We can then output our country name. And we can make this dynamic using the # and then the {}, and then output the country. If no countries are available inside the database, we can then follow up with an else block. Just on the same level as each, we can add else, which I'll put a list item with the text of, there are no countries. Now if we save this file and then over to our Projects and then reload our forward/countries routes. Then scroll down. We don't quite see the information which we're expecting. We were expecting a list of countries. Again, a lot of strange looking code down below. The reason this is happening is because we are not awaiting our data to come back before we're trying to render this to the screen. This is one of the problems we mentioned before, because we're using a single weight, we need to await our data to come back from the database before we try to use it in our application. If we go back over to the hotel controller and the list all countries, we have this function marked as a sink, but we're not awaiting the hotel.distinct value to be returned back from the database before we pass it to our templates. Hopefully now if we save this and then reload, we now get list of countries being displayed. If we click on one of these, we're then it taken to our route of countries, forward slash and then Jamaica. We have an error down below because we're not handled this route just yet. Let's try another one for the Netherlands. These all appear to be working. It would also look nice too, along with this country name if we can also put in a image related to this country. We already have the country images, which is stored inside of our Images folder. Public images. Then we have some countries with images down below. Let's go ahead and make use of these images in our templates. So just under our link, go on to the next line. Then we can set a image indentity in one level. This also links to the same route above. If the image needs a source, is it going to be equal to o back ticks, the forward/images folder, the country's folder. Then we can add in the country name, which is simply country. Then we need to add the.jpg extension onto the end. If we now save this and then go over to our forward/countries routes, reload. It looks like we're typing errors. So let's take look at this. It's just because we've added a semicolon in our templates, which we don't use in pug. Refresh. There's our country images next to the name. At the moment, this looks like they are now all working but at the moment though we can't be too sure. This is because we only have one hotel in each of these countries. So we don't know if it's showing a distinct value just yet. We can test this by adding small hotels to our database. I know it's a bit repetitive, but let's now go ahead and add the remainder of our hotels. Then we can use this for the rest of the project. Let's go to forward/admin, forward/add, down to the bottom, I'm going to add hotel number 6 and then crop the Lorem Ipsum. Go to lipsum.com, I'm going to create two paragraphs and then hit "Generate". Copy this and paste in our description. Hotel 6 has the image, the star rates in this time of four, the country, Sri Lanka, the costs, 57. This cone can be available too. Admin/add, Hotel 7. Add the description and image. The star rating of five, the country of USA, 78. Keep this as available. Back to our admin routes. Create hotel 8. I'm going to go up to hotel 12 to much all images which have been provided with the course. So add this in and hotel 8, the star rating, the country of Maldives and the availability as true. Now we can see we already have more than one hotel in the Maldives. Back to forward/admin, forward/add. Hotel 9. Based on a description. This one can be a star rating of four. The country of Mexico. Cost per night. Confirm. We need it now, let's go on to the admin adds and creates number 10. [inaudible] four, hotel number 10, the description and also the image which is number 10 too. Open this up, the star rating of three. Let's again go for Mexico. Have a price and then hit "Confirm". Admin adds, hotel 11. The star rating, let's go for four, the country of Thailand, cost per night, 39. Confirm. Finally, we can add the hotel number 12, which is the last one. Sounds at the bottom. Hotel 12. The star rating of three, Dominican Republic, 56 and hit "Confirm". Great. Now over two mLab we can now refresh. I know this is little bit boring and repetitive. But now we have all 12 hotels now in the database. So we have plenty of information to now work with in our projects. So I've provided 12 images. You can of course add more hotels, if you prefer. There is now more than one hotel located in the Maldives, Mexico, and also the Dominican Republic. Now if we go over to forward/countries and then hit "Enter", scroll down. We can now see all of the extra countries which we've added. There is only one of each volume. So there is only one Mexico, one Dominican Republic, and also one Maldives, which means that with distinct values are now pulling in correctly. Now we're going to move on to looking at the aggregation pipelines. 26. The aggregation pipeline: The aggregation pipeline is an interesting feature of MongoDB. It basically allows us to process data one stage at a time. Currently, only Mongo documentation from before. If we go to the menu on the left, we can go up to the aggregation section, click on this. If we scroll down, we see a diagram which has an example of how we can use the aggregation pipeline in our projects. This example uses a collection called orders, which we can see here. Its comparable to our hotels selection, which we have in our database. This image shows free stages of the pipeline which results in the data we eventually want over on the right-hand side. Each stage in the operation could do things such as filtering, grouping, or sorting documents until we end up with the correct data. The first stage in this example here shows four records inside of our collection. We then sets a matching stage, we then declare that we only want to match any documents with the stars code of A. Over on the left-hand side, we see the only freedom of this A code, and the last one has D. Therefore, only three of these four documents can match, then these three move on to the next stage, which is in the middle of this diagram. The stages are grouped together by the customer ID, which we set here with the group stage, where we're grouping with an ID field. These two have the same Customer ID. Therefore, these are grouped into the same results. Then the third one is unique too. We now filter down to two results. The second part of this stage is to group together the total amount of these two orders the same customer has placed. This is what we see in the total of the final stage. To find out more about what we can do for each of these stages, we can click on the sidebar and go down to aggregation reference, then aggregation pipeline quick reference, then scroll down. Here, we see a list of all the stages which we can use. We've already seen some of these in the examples before, such as the group stage. We have group just here, and also scrolling further down. This is the match stage which we've also seen. You can click on any of these listed stages and find out what each one does. Or I'm going to run through some of these examples now, inside of our projects. If we go over to the hotel controller.js file, we have functions to get all of the hotels and all of the countries in the database. Which of these two just here, but what if we want to be a little bit more specific about the data which we got back on the homepage. I also want to show these hotels both limit the results to be just nine so we don't have an overcrowded homepage. Once our database stores a lot more different records. Also the same for the countries too. For these we can use the aggregation pipeline to filter down these results for the homepage. Let's create some filters to filter down these values. Exports.home, I'm going to call this function the homepage filters. We set this up as an async function so we can use await, pass in the request, the response, and also next. Then a try-catch block to handle any errors, passing the error. Then call next with this error. Let's first deal with filtering the hotels inside of the try block at the top. We can use the aggregation method. First of all, let's set up a constant to hold these hotels in. Const hotels equals awaits our hotel model. Then we call a method on our hotel model, just like we did above with distinct and also for the find method. But this time now we use hotel.aggregates with a semicolon at the end. This takes in an array of the various stages. Add an empty array inside here. The first stage I'm going to use is the match stage. Open up the curly braces, $ symbol match. Then we want to match the hotels which are available. Set the available fields to be true, then add a comma the end. Next step, so the homepage it doesn't get too crowded. The $ sign sample stage. Will randomly select the number of documents which we specified. $ sign sample, we can set this sample size to only return nine documents. You can of course change this to be any value which you prefer. This aggregation which we setup will return towards nine random hotels, which have their availability set to two. We can now do a similar thing with the countries. We also only want to show nine random countries on the homepage too. Just like earlier when we were dealing with countries, this needs to again, only return each country once. Even if there's more than one hotel per country. To do this, we have the group stage. Let's set up a number constant this time called countries, set this to be hotel. aggregate, passing our array. The first one is going to be the group stage, $ symbol group. When we're using the group stage, we also need to pass in an ID with -id is equal to output our documents with an ID field which contains the distinct group by a key. This field is mandatory and we're going to group this by a key name of $ symbol country. This will group all of our hotels by their country and then separated by a comma. We can again setup our sample, the sample, just like the hotels is going to return the sample size of nine countries. The group stage will take in all countries as an input, then I'll put one distinct value. For example, if there are two hotels in the USA, we only get the value of USA ones inside of our array. Now we've created our filters. We want this data to be displayed on the homepage. Let's go and start this over in the index.js. Yes. We can change the controller up at the top. So for the forward slash home route, instead of using the hotel controller to homepage. We can change this to be the homepage filters, which we'll setup, back over in the hotel controller. If we now scroll up and find this export.homepage, we don't need this anymore, so we can comment this out. Finally down in our filters, down at the bottom, the final stage of this try block is to do a res.render. We want to render our index page, which is the homepage. Then inside here we're going to pass in our two values, which is the hotels and the countries. We can loop through these on the homepage, parsing the countries and then now hotels and actually we also need to await of countries too. So as a side note, awaiting to promises like this, using await here and also await here is not a great idea. This is something which we'll come back to you and fix later on. For now though, over in our index or poke file, we can deal with these countries and also the hotels. So for now though over in our index.pug file, we can now deal with these countries and hotels data. So go to views and then index.pug. Let's close the sidebar. At the moment if we go to our home route. So click on the logo at the top. On this homepage, we have an error because we're not yet parsing any country detail to this hotel mix in. Let's now go ahead and loop through all of the data which will now be in past and then we can display this hotel mix-in for each one. After our text of CO, create on another list, we can then loop through all hotels with each hotel in hotels. Remember hotels is the data which has been passed to this template just here. So each hotel in hotels. For each one in the database, we also want to display this mix in and as well as displaying this, we also need to pass in