Projects in Node.js - Part 3 - Meeting Reporting App | Patrick Schroeder | Skillshare

Projects in Node.js - Part 3 - Meeting Reporting App

Patrick Schroeder, Teaching JavaScript Courses

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
9 Lessons (1h 16m)
    • 1. Project Overview

      0:58
    • 2. App Setup - Backend

      10:10
    • 3. App Setup - Frontend

      9:54
    • 4. User & Note Models

      8:24
    • 5. Add Validation

      12:16
    • 6. Controller to get All Users Notes

      7:28
    • 7. Controller to create New Note

      9:51
    • 8. Async Module

      10:18
    • 9. Filter by Member

      6:12

About This Class

Download completed course files here

Welcome to our third project - building a meeting reporting application. In this project, we're going to build an app that that allows users to create Notes.Then we'll display all the notes our users have created on the front page. We'll also create a filter method to display Notes by the user of our choice. 

In this project we'll explore how to validate user input, how to retrieve and display errors based on incomplete user input, and how to find more then one document at the same time using the Async module.

We'll be using Swig as our templating engine of choice.  Along with express and mongoose to form routes and connect with a database.

Part 1 of this course can be found here: Mongoose CRUD App

Part 2 of this course can be found here: User Login App

Transcripts

1. Project Overview: Hello and welcome back to the introduction of our third project building a meeting reporting application. In this project, we're going to build an app that allows users to create notes, then will display all the notes. Are users have created on the front page, will create a filter method to display notes by the user of our choice in this project will explore how to validate user input, how to retrieve and display errors based on incomplete user input and how to find more than one document at a time. Using the A sink library, we'll be using swig as our template ing engine of choice along with express and mongoose toe form routes, and connect with a database. 2. App Setup - Backend: in this video will create the basic configuration for a meeting application. So lets navigate into our projects folder. So I'm in our projects folder in my terminal and if I open up sublime text, you can see I have a projects folder and inside that I have are logging app application so inside of my projects folder and want to create a new folder and I'm going to call it meeting up. If I open up my sublime ticks, you can see we have the meeting APP folder. I'm going to go into that folder and inside of our meeting APP will create a few new folders as well as a main dot Js file. So it's actually gonna be called app dot Js. So say touch and then app Dodge s, which will be the main entry point for application. The Fullers that I'm going to create. I'm going to be called controllers, public routes and views. So these are the four folders all create and I'll just hit enter. And now if I go back to my sublime text, open it meting out, you can see that we have the app dot Js file as well as these four folders. I like to create a package da Jason file by typing in PM and net And then when prompted, I'm just gonna hit enter a few times. Then it will say, Is everything looking fine and I'll say Inter again. So now I should see a package thought, Jason, Right here. Now I'm going to install the modules that will need for this application. At this point, you can either follow along with me or you can just download the package thought, Jason, that's currently in the resource is folder and hit NPM install. So I could say NPM install dash, dash save and I want to be using express Bharti parse er path mongoose swig and a sink So again, his body dash, sparser path, Magoo swig and a sink. So we'll download all these modules for me, and it's gonna add them into this package dot Jason, can you can see the modules get automatically dropped in. So this package thought Jason file will be included in your resource is folder. So you may want to just add this package thought Jason into the current folder and file structure that you have and just type in PM installed, and then it will bring down the current versions that I'm using in this project. And the reason why you might want to do it that way is because if in the future, if there's breaking changes that occur than the code that we write might need to be changed as a result. So let's go over to our app dot Js file and open that up and we don't want to do for this application it Since we've already done an app dot Js and are logging app, I'm going to copy that over and make some adjustments close out this one. So in our application, we are currently using express we using APP Equaling Express. We're using Body Par sur Ma Goose and Path. We'll start off by getting rid of this controller going to change the name of our database to meeting up right below our Mongu stock connect. I'm going to set up the view engine, so if you'll recall one of the modules that we downloaded was called Swig and Swig is the template ing engine that will be using to display our views in this application. The next video we'll be taking a more in depth look of what Swig provides to us. But for now, let's go ahead and requiring swig and set it up. So first are requiring swig, and then I want to set our engine two html and then I'm also gonna say swig that render file. So now we can use the dot html extension in our views folder and will be rendering certain attributes using swig and these air mostly gonna be looping variables. And instead of saying app that use, we're gonna use something different. We're gonna say app dot set because we're using a view engine. So here we're going to say app that said and the first parameter is going to be called views and this tells express where to look for our swick files in we can say app that's of use so we can say path thought join, and we're gonna look inside of the directory called views. So we did create a folder already called views, and this will contain all of the HTML files that we create. In addition to defining our views, we also need to define our view engine. So we need to say app that set. And then we need to tell our view engine what kind of files that will be creating, and they're gonna be HTML. And this is the standard pattern that you're gonna see whenever you're using a template ing engine. And this applies to any other such a Z handlebars or jade or E. J s. And just like we did in the other application, we need to set a static path for or public directory. So in this case, we need to say app that use, we can say express thoughts static. And then we need to say path thought, join double, underscore Duerr name, and we need to look in the public directory. And again, this will tell express toe Look in this public folder in her application, we're going to be defining all of our routes within a specific file located within this routes folder. So since that's the case, we can get rid of these two declarations of routes within ah, rapturous file. And as I mentioned, we're gonna be creating a permanent routes foul. So let's go ahead and to find that up above. So I'm gonna go ahead and define that, and I'm actually gonna put it above this monger stock Connect, trying to save our routes he's going to equal require. And we're gonna look inside of the routes folder and we're going to create an index dot Js file. So now that we've required in this file that we're gonna create in a moment, we still need to indicate the path that these routes will take. So we're going to say that this foul this index dot Js file is going to define the routes located at the root of our application. So in order to define that, we have to se app that use and then define that location. So this backslash indicates that we're looking at the root base of our euro, and then we're going to say routes. So this routes is the variable routes that we declared above. So I'm going to create now this index dot Js file that I've been referring to by right clicking on my routes folder and saying new file and then I can say index dot Js. Now this new file lives inside of the routes folder and the reason why we do this should be pretty clear. You don't want to have all your routes within one file, and there's actually just one more folder that I want to add to our application. That's in this public folder. So I'm actually going to do this one through my terminal from in a CD into my public folder . I must say em que de ir CSS. That was a CD CSS, an insider CSS folder. I'm going to create a new file. It's gonna be called styles dot CSS. Now. If I go back to my sublime text, I should see public CSS and styles at CSS. So that does the basic scaffolding of our application. And in the next video, we'll take a look at swig so that we can understand the HTML files that will be building. 3. App Setup - Frontend: Hello and welcome back to part two of building our meeting application. In this video, we're gonna talk about Swig. So for this video, I'm going to include three HTML files that you can add into your views folder. So it's just gonna be this views folder, and it's gonna include an air dot html page and index dot html page and a new note dot html . So let's take a look now at this index dot html page. So this page is going to include title variable that we're gonna populate using Mongoose. We're gonna reference in our style sheet. We're gonna reference saying bootstrap and I'm just pulling boots dropped from the cdn below that we have some bootstrapped template ing to create in that bar. And within her in that bar, we're gonna have a link for home and a link to add a new note blow that will have the H one tag for virtual meeting notes. That's going to give us a list of notes that have been added to our application. This select I D. And these options is going to represent a clickable box that will display all the users that we have added to the application. So this is a looping functionality which will loop through all the users, and this is swig right here. So this percentage four users in users will allow us to display all the users from our database. And then we have a button to filter the notes based on which user we have selected blow that we're going to display all of the notes. So this is saying percent four notes in notes. So, just like the users were going to iterated through all of the notes that have been submitted to our database and then display them and member name created on project work yesterday, all of these are going to be created within our notes model, which will create in the next video. So you can see the two main elements that were using for Swig is these four note in notes and four users in users. So now let's go ahead and take a look at this swig documentation, and to do that, let's go ahead and Google swig and then no Js, and the first result that we get is going to be what we want. So this is developed by Paul armed Armstrong and I'll click on this. And this will give us all the features that we can use within swig. So you can see one of the things is page name, pipe title. And we are using this within our template and right under that it says four author and authors. And it's what we're using. And you can see that that's really the main purpose of Swig. So if you're looking for just a simple template ing engine that gives us variables and four in loops, then suite is really a nice solution. There's more to it so we can click on this documentation link and it will give us some more uses. It will give us a P I and as well it's amore examples how to use and how to set up Swig. Yes, we've actually just about set up our application and in order to see what our app is going to look like right now, we need to do two things. Let's first start up mongo db. So I'm going to navigate into another command prompt, and I'm gonna type mon God, which will start mongo db for us. Okay, so now that that's running in order to reference or index and our new note HTML pages. We have to create these routes. And, as mentioned, we included a Routes folder with an index dot Js file, and this file is going to contain over routes four or application. So what we need to do this follows first include Express, and the reason we need, including Express is so that we can use the router. So with express define, I can say expressed DOT router, and now I can start creating my roots in order to use Swig. We're going to be creating controllers because, remember, we're going to be adding stuff to the database like users and notes. Then we're going to grab those users and notes and display them in our application using controllers. But for now, we don't have any of that stuff set up. But we can still take a nice look at what our application currently looks like by creating a couple of new routes within our index dot Js. And this is the same functionality that we used in the previous application. But this time we're going to say router dot get, and then we're gonna pass in the route. So the round is going to be at the root location over up, and then we need a passing a function with the request and response object. And now we're going to render the index fall. So because we've already defined our views located in our views folder when we say Render Index Express will look inside of this views folder to determine what page that it should render. So we could say rez dot render and I could say new note, and it would render this new note dot html page. But instead, of course, want to render the index page. And again, Rider is basically taking the place of app. So just as we used app dot get in our logging app. If you take a look at that and we go below, you can see we're using app dot get, and then we're rendering the index dot html page. So it's the same thing. Except instead we can use router, which again gives us a nice separation of concerns for application. Now I'm gonna save this file and let's go ahead and test our application. So I'm going to start our application just like we did previously by saying no bone and then app dot Yes, So we get thrown an error here, and the reason why we get this error is because you need actually export router. So we're using router basically instead of app, but we actually need to export it so that it gets seen by our main app Js file. So we just need to say export module thought exports equals router. And this is just a standard pattern that you're always gonna use whenever you're using express start writer. So I'm gonna re save this fall, and we get our app listening on Port 80 80 message so I never get over to local host 80 80 . It's not appearing perfectly, but it is being loaded. And the reason why it's not showing this each one that we've defined in our index is because we haven't set up our styles and we're only gonna really be adding a couple lines of code here. So I'm going to go into my public CSS this styles that CSS. So let's start off by adding some padding to the body and I'm gonna say body and inside of that I can say patting 50 pixels, and I'm going to define our font also. So let's go ahead and use 14 size pixels. Macedo Grand A as our defaults and and will define a couple other fonts. And I'm just going to define a color for a lynx and B 00 b seven ff, and I'll save that. Go back into my app Js file, make a new line and saves that I can restart my server. Reload the page and we can see that this fixed the padding for my virtual meeting notes. H one. So that does it for this video. We briefly discussed swig and we took a look at our HTML files and what they're composed of . The next video will create our two models that would be using for this course, which is one for notes and one for users. 4. User & Note Models: Hello, guys. And welcome back to part three of building our meeting application. So this is where we left off in our index dot Js file will read to find a writer dot Get and we rendered or index dot html file. The one thing that we didn't do is look at our a new note that html file. So let's do that. Now. I'm gonna open this up and it looks pretty similar to our index file. It includes a variable for our name we're requiring in the CSS file as well as our bootstrap files we're adding are now bar. So if we scroll down a little bit, I inserted a comment which says Show errors here. And this is saying that if message dot length is greater than zero, then we're going to display this message. So this is basically checking to see if a message variable exists, and we're basically going to show this message if there's ever an error when saving a new note and below that is going to define the information when we're adding a new note. So we're going to allow the user to select one of the users that we've added and then we're going to let the user fill out some information. So they're going to be able to choose from one of the projects that I've just added here. So we'll give the user three different options blue. That will add an input feel for what did they work on yesterday? What will you work on today in any impediments or any problems that a user encounters, and then we'll have the button to actually save the note and to make this work for now, let's go ahead and add a route for this new note dot html page. So what I'm gonna do is just copy this and change the parameters. So instead of getting the room, we're gonna be getting new notes and we're going to be looking for the new no dot html page . And I believe this should be new, no dot html and we'll see that and we'll see that our app has restarted. I'm gonna refresh the app and click over this new note and this should actually be just new notes. Save it. If I click new note, then it will load up this information and this isn't loading for me. The style because I need to change the name of my style. That's CSS file. And now work. This will be corrected for you. So in this video, I want to create the two models that will be using in order to populate the users as well as populate our notes. And it looks like I forgot to add the models folder. So I'm going to do that within my terminal. So I'm gonna kill my process, scroll down a little bit, and I'm going to create a new folder and it's gonna be called models. Now, I'm going to see the into my models folder. I'm going to now create two files. The 1st 1 is going to be called User Thought model Dodge A s, and we need to say touch user dot model dot Js and touch, then note dot model Dodge A s. And then we see the models folder and we see are two new files. Now you can see in this instance I've capitalized the name for a note and for user. And this is a fairly common naming convention. When you're creating models is to capitalize the name of the model. So let's start off by opening up our user dot model dot Js file. And for this application we are going to be creating any kind of registration. We're just going to be adding the users directly tour application via the Mongo Shell now to create the model. First thing that I need to do is requiring Mongoose. Now I need to define a reference to Schemo, which is Mongu start schema. So now I can create new scheme owes and I'm just gonna create a a new schema that's called user Schema, and I can say user schema equals new schema. Now I'm going to define the properties of my user schema and we're just going to include a user name which has a string as well as a password, and that will also have a string. And below that, I just need to export our modules so that we can use it in other files. So I need to say module don't exports equals Mark Mongu stop model and then user, and we're using the user schema, so we'll save that. Now let's switch over to our note that model Dodge A s fall to find the properties of our no model. So did the same thing. By requiring in Monagas is, well, a schema going to create a new note, schema and name. This note schema equals new schema. Our first property is going to be a member name and will make that a string. Don't put a comma after this curly bracket. The next property is going to be a project, and that's going to be type string as well and would, instead of required field to true. Next is going to be work yesterday. Well said Type to string and required to True will say work today and we'll set type to string and require too true well to find another property called Impediment. And this is going to be type string required. True and let's also had a default. So if nothing is submitted for this field, it will default to none as a string and finally will add a created on property. And this is gonna be type date. And we like to add a default whenever we're using a date, and we'll say they thought, Now that will do the same thing that we did in the previous example and export our model and this is gonna be called note and we're using the notes schema. So that concludes this video in the next one, going to set up some custom validation. 5. Add Validation: Welcome back to part four of our meeting example application. In this video, I'm going to show you ways where we can set up some custom validation. So the first thing that we're going to do is open up our user dot model dot Js file. And what I want to do is customized this user schema so that before saving the user name to the database, I want to capitalize the first letter of this user name. So to do that and we actually can use some middleware and this middleware comes shipped with Monagas. So if you navigate over to Mongu slash docks the left hand side, you'll find some links and you want to scroll down to where it says middleware. So if I click on that brings us to this middleware page, and all we have to do is come down a little bit and were given the option of using a couple of different hooks. Hooks allow us to redefine the data before actually saving it to the database. So in this example, we can say schema dot pre passing save and do something. So this is saying that before we save the database object do something to the model, and this is probably the most common piece of middleware that you'll see in other projects . Is using this dot pre method? There's some other options. If we scroll down a little bit, we have parallel. We have post, So this would be after the new object is getting saved. Want to remove something or validate something? Here's another one for fine. So before looking for that particular object, do something else. So in this instance there logging out the query and they're setting the date to now. As I mentioned, we're going to go ahead and add this pre hook toe our user model in order to capitalize whatever it is the user person for their user name. We start off with the name of the schema, which is user schema, and we say dot pre the first parameter says before doing something. So this is going to be before saving and you'll see how we're using the same method in our controllers when we're creating a new user or a new note. So then let's do something so we can say function, and we have to put in this next, and we have to use next because this is a piece of middleware. So I'm gonna say next and we'll do something up above here. That's what we'll do is going to capitalize. User name. We can do that by saying this Start user name dot Char at. So we're only gonna be capitalizing the first letter and I will use the Method two local upper case and I'm going to concoct this with this thought user name thought slice at the index of one. Now, the next thing that I want to do is I want to add a validator for our member name in this note thought model. So when we're adding a new note, we're going to loop through all the members that have been added and display them in an input type box. So I'm gonna open up this views and this new note dot html And if I come down a little bit when we're entering a new meeting, though we reiterate over all of the users and you can see we're using this name equaling member name. And this is what we're grabbing and displaying from the model, which is this property right here. This member name So what I want to do is make sure that somebody has clicked on something, so they're not just leaving it blank. And I can add the validate name and this validate is particular to Mang Goose. So if we want to add a custom validator, we named the key validate and we're going to create a function above that's gonna be called member name validator. And this will validate that there is actually a user name that's been clicked on. So now above is well, create my function, and we actually have to put this into an array. Whenever we're using Mongoose Validators and its side of the Saray, I'm going to declare my function and it will take a value. And I'm just gonna return the value that length being greater than zero. And the fact that the value does not equal select name and select name is what's given to us by default. And the second parameter would thin. This member named validator function is going to be a string which will be our custom error text. So well, we can say select a valid member name and again, this select name we can find right here in our new note. HTML. Go ahead and save that fall, and what I need to do is I need to restart my application to say no mont ap Thaci S and I'm going to navigate now into our application. And if I click on new note, we can see the name and it's asking for us to select the name. And this won't populate anything because we need to create some users. And underneath that, we have select project. When we've created three possible projects for user to select from our application doesn't have anywhere for a user to actually register. So what we're going to do is let's go ahead and create three new users and just add them to our database. I first want to make sure that I have mongo DB running. So with mongo db running, you go ahead and open up a new terminal. So in my new terminal with Mongo db running, I can say mongo Morongo, and this will navigate me into my mongo show. The name of the database that I'm using for this application is meeting app. So if I go out back into my app dot Js file, you can see that we're using the meeting APP database. So in order to use that database, I'm going to say use meeting APP analysis switched over to DB meeting app. No, we haven't added anything to this database so far. So if I type the command show collections, I should get back nothing. And that's what I get. So let's go ahead and create a new collection for this users model that we've just created . So to do that, I'm going to say, db dot create collection and on a passing a string of users when I get back a response. Okay, one. So now if I say show collections, I'll get back this users collection and this users collection represents the model that we've created right here this user dot modeled dot Js. So let's go ahead now and insert a new user. And to do that, all I need to do is say, db dot users. So the name of the collection and dot insert parentheses, curly brackets. And remember, we've defined a user, and I'm gonna name this user Joe, and I'm also going to define a password, and we'll just say four for four and I'll close this out. Can we get a right result of in? I inserted one. Now, since we're manually inserting users into our database v the show, it's not going to apply the pre save hooks that we defined in the model. So you would need to create some registration. And once a user submits a name, then it will capitalize the first letter of the user's name. So actually, what I'm gonna do is going to say, db dot users don't remove. And this will remove all of the users that have added. And I'm just going to reinsert a few users, and I'm gonna capitalize their names this time. So I need to say DB that users dot insert and it's supposed to be user name. I put user the first time. And just for clarification, you can put quotation marks around the keys and the values, or on lee the values so I can say user name and then Matt, for example. And then I can say password. And then whatever the password is, we can say 444 and this should work or not. So sorry. So I forgot. Put it right here. So let's say we definitely have to use quotation marks for the value, but not necessarily for the key. And we can see gets inserted. So there you go, and I'm gonna insert a couple more, and I'm just gonna change the names. So this is gonna be John, and I'll change this to marry. Okay, so now I've added three new users Matt, John and Mary. So now let's take a look at those users. I can say db die users not find. And it will spit out the three years that we've created. So now that I've added these three users, we can get toe work on adding our controllers, and that's what we're going to start doing on the next couple of videos. 6. Controller to get All Users Notes: hello and welcome back to part five, a building or a meeting application. So in this video, we're going to add the controller files, and we're going to create a method in our controller that's going to display all of the users. And it's gonna grab the users from our database and again right now, if we look in our new note dot html page, we have added three users, but it's not displaying anything. So the first thing that we're going to do is create two new controller files, And to do that, I'm going to right click in my controllers folder, and I'm going to create a new file. And the first follow that I'm gonna create is gonna be called notes dot c t or oh dot Js. And I'm gonna do another file right clicking on controllers and I'm going to name this file a sink dot c t r o dot Js. So now in my controllers folder, I'll find two new fouls. So what I want to do in these files is I just want to require in the models that were going to be using and create an exports variable so that we can use these controllers and other files, so it's going to be the same for both files. First, I'm going to say you strict and I'm going to create a variable for our notes model and we're going to require in the models fall just located at dot, dot, slash models, slash note dot model and the other one is for our user model, which is far user Equalling, requiring in our user model just I thought slash models slash user dot model trying to save this fall. And I'm just gonna copy this over to our notes controller, and I'm gonna save that one as well. We're going to create a method, and it's going to be called All users notes. So let's go ahead and create the exports for this method and, as mentioned, is gonna be called All users notes. And it's gonna be a function which will take a request in response object. And what we're gonna do in this method is we're just going to find all users. I'll save that. And before we fill the sin, let's go ahead and create the route that will be using for this controller. So let's go into our routes and then our index dot Js file. And what we're gonna do is we're still going to use this new note route location, except we're going to be rendering it in the controller. So what we can do is we can get rid of this and instead we're just going to pass in the method that will be creating here in a second. So it's gonna be located in our notes, notes controller and then the name of the method, which is all users notes. So this notes controller is a variable that we need to define at the top of our file. We're going to save our notes Controller is equal to the notes Dark Controller file, which is located in our dot thought backslash controllers backslash notes dot c t Orel. I'm going to save this file now and let's create this all users notes controller. So go back in here. And the first thing that we want to do is one a look in our user model and we want to find all of the users. So what we use fine and put in an empty object. This will return all of the users that have been added to our collection. Let's go ahead and sort this by user name. So this will make sure that our user names are sorted alphabetically. And then after sorting, we need to make sure that we execute this function. And when we're using this execute method is a synchronous. So it takes a function that returns an air object as well as the results of whatever it is that we're trying to do. So users will represent all of the users from the database. So right here will say, if there's an error, let's just logged the air for now and we'll say, air getting users. And we can say otherwise, we're going to render the new note. So just like we use Red Star render in our index, such as far, we use it here. I'm gonna render this new note, and we're also going to pass a long couple of variables. So the 1st 1 is the title, and we'll set the title to new note, and we're also going to say users to users. And this is one of the things that we have to do with. Swig is since we're iterating over the users that's this variable that we're defining, and we're also defining a title variable, which will print out a string of new note. So let's switch over to the views and new note that html page and if we scroll down a little bit, we can see for user in users. So this users right here is this users right here. And if I go up, we're defining the title, which is right here. It's You can see it's in these curly brackets. So if I save this now, that should be enough to display all the users that we've added within our select I D input field. So let me go back and refresh the application, and I'll go to new note and select name. And now we get the three users. In the next video. We're going to create a new post route that will allow us to fill in the rest of these inputs and save them to our database. 7. Controller to create New Note: in this video, we're going to create the functionality of being able to create a new note. And to do that, we're going to be adding a new method in our notes, Doc. Controller foul and the name of their method is going to be called create note. So we'll open up our notes stock controller, and I'm gonna scroll to the bottom and we're going to create a method, someone to say, exports that create note. And it's going to equal a function that will take a request and response object. And inside this function, we're going to add the functionality of creating a new note. Go ahead and save this. And before we fill the sin, let's add this route to our index dot Js file located in the routes folder. So I'm gonna put this right below or router dot get. Since we're gonna be using the same route instead, we're gonna be using a post call. It's still gonna be to the new note location, and we'll be using our notes controller, and we'll be using the create note method. I'm going to switch back over to my notes controller and fill in our new method So the first thing that will do is create a variable reference for our model we're gonna save. Our new note equals new note. And now we're able to use the different properties of our note model by saying new note and then thought and then the name of the property that we're looking for. We'll start off by saying, you know, thought member name is equal to request stop body thought member name. Let's go ahead and open up this views folder and I'm gonna open up this new note that ht mouth just to refresh your memory. So this new member name Excuse me? Just this member name is what we're going to grab right here. And we've attached our member name to each one of the users. We'll switch back over to our notes controller, and I'll saying, you know, thought project equals request Stop Body Dark Project. You know that work yesterday equals request stop body that work yesterday. New note that work today is equal to request stop body that work today and new notes dot impediment is equal to request our body dots impediment. So now that we have attached all of our properties from the view we can say and you note that save and let's pass in a function and we only need to take an error object. Now we're going to define this air a little bit more explicitly than we've done in the past . So if there's an error, we're going to set an error message to be displayed in the view. So let's create a variable four our error message. So if there's an error will say Sorry, there was an error saving and then we'll pass along the error. So now it's render something, so we're just gonna render this first. We need to define where we're rendering it, and we're rendering it in the new note page. And the second parameter is an object which is going to contain the air that we're sending along. So the title to our error is going to be well, say note, and then you note error and we'll pass along the message as air message from the variable that we defined up above. So if there is no heirs, I wouldn't send a log back to her console that are meeting note has been saved, and I'm going to redirect the user to the front page so I can say Resident redirect, you know, pass along a success number, which is 300 and send them back to the index portion over up. So I'm going to save this file, and now we should be able to save a new note, toe our database. I'm going back. And every time I save this file, I see that my super has been restarted. So that's good and there's no errors. Let's go back to my roots 80 80 and hit new notes. I'll select the name will go with John. I select a project. Work yesterday was put something nothing and none for impediments. And what save? Okay, Good. It looks like we get an error here, So let's go ahead in the bug. This and it's saying, cannot re property member name of undefined. Hey, guys, I'm back. And the problem with this is what amounted to a kind of a rookie mistake. But it's a really good teaching moment because this air that we were seeing wasn't I had nothing to do with not being able to find this member name, But it was something in our app dot Js file and it's the way that we define these users and these routes and the sets. This all happens synchronously. So one thing loads and then the other. So it's actually very important how you're defining everything within this file. I accidentally defined my routes above body part, sir. So in our index dot Js file and hence in our notes stock controller file were using body parse er in order to get elements from the view. But we haven't loaded it into our app yet. So all of this is you can think of this as middleware body Parsons middleware. And we need to make sure that we first define our middleware up above any routes or any other files that's going to be using body part, sir. So once I put that blow this everything is gonna work. Now I've edited this file in the resource is folder. So you only have to change this if you're currently following along. So once I save this now, everything will work. So now we can see that our app has been restarted and I'm going to go and reload my app. I'm going to go over to this new note tab and all. Select John for Cold Review and put anything here. Save it. And I get redirected to the front page, which is what I expect. And let me look at my consul and I get our log. That meeting note has been saved, so we can assume it's in our database. And since I'm already here, I'm gonna open up the shell and I've done some stuff in here, but I'm still in our meeting app so we can say db dot notes that find I thought pretty and I should see the note that I just added, and I do so the other thing that I wanted to show us how the air functionality should be working Julissa had all filling anything here. Ah, pretty. If I click save, I should get a message and see, I get this error message above. Remember, we inserted a string in our air function saying, Sorry, there was an error saving and then we get the air message. So it told us in these in the work yesterday and the work today and in the path impediment , it's all required. So now that we're able to save notes, let's go ahead and make sure that we can display these notes when the application is first loaded and we'll do that in the next video. 8. Async Module: hello and welcome back to Part eight of building our meeting application. In this video, we're going to create the controller to add all the notes and the users to our front page. So right now, if I open up our index dot html, there's some code here that's going to scan for user and users. And there's also some core below here that's going to scan for note in notes and is going to display the note information inside of ah container. So since we're going to be looking up two different collections, we need to use some kind of a hump er library in order to return the results of both queries. At the same time, there's a couple different solutions for this. A new popular solution is to use module called Bluebird, which lets his use promises. Another one is to use the A sink library and a sink has been around for a long time. And let's go ahead and take a look at this A sink library now. So I'm gonna google a sink and the node, and the first result is going to be this a sink library and utilities for node and the browser. This a sink library provides us with a number of different methods. The helpers, a synchronously execute code. And here's a couple quick examples. So a couple of the methods that a sink has they have a map. They have a filter, they have a parallel, and they have a Siri's. So parallel is what we're gonna be using. And what will be doing is within this first function call. We're going to be making a find request inside of our note model. And then in the second function, we're going to be making a fine request inside of our user model. So we're basically be finding all of the notes and all of the users, and this callback is going to represent the results of first the notes and second the users . So let's start off by going into our a sink controller dot Js file. And the first thing that I need to do is require an A sink. So it's a package that we've already downloaded at the beginning of this project, so it required in, and the method that we're going to export to a router is going to be called home page. So to find that now. And of course, it's a function which takes a request and response, and I'm gonna leave a comment here. It will say, Gather all notes and all users so we'll save that and I'll flip back over to our index dot Js file in the Routes folder. And now let's replace this writer dot get So we're still going to be accessing the root page. But instead we're going to be using are a sink controller, and we're gonna be creating that home page method in a moment. And of course, now we need to require in this a sink controller. So we'll do that up above. I will say var a sink controller equals require dot dot controller slash a sink dot controller. So what that saved? Let's go ahead and create our method. So first off will be using the a sink dot parallel method, and it's going to take an array of functions. In the example that we saw, it took two functions and a call back, so this could be a zoo. Many functions as you like. You can be 234 etcetera. So we'll start off with a function that takes a clawback. I'm gonna create a variable for query. And I wouldn't set it to know dot find So this will find all of the notes that we've added to our note model. And I wanted to set up this query variable because I want to make sure that I sort my notes and I'm going to do it by the sending. So I'm gonna look at the created on property, and I'm going to set it to descending. And I also want to limit the number of results that we get back to 12. So mongers comes with a handy limit method, and I can pass that in just like that. And then I need to make sure that once I've sorted and limited that I execute the query and the execute is going to take a function which takes in air and the response object which will call notes. And since I'm using a sink parallel, I'm gonna pass in this call back, which is going to contain an air as well as the notes now is to find the second method that's going to get all users and what I can do here to save a little bit of time is this? Copy this over. I'm gonna come up to the where this function is and copy it. You know, skip a line and paste right below, so we'll change our query to be instead of no, we're going to query for all the users and instead of created on go ahead and sort by user name and we'll sort them alphabetically so we can say one. We'll get rid of this limit and we'll change our notes to users. Okay, so now we have both of our functions set up. And if we take a look at the docks here, we can see that once we have our function set up, then we want to pass in the callback, and it's gonna be after the array so we can say comma after the array and we'll make a new line here, snow say function. And remember, this is the callback function, and it's gonna contain an air as well as the results. So if there's an air in retrieving either the users or the notes for now, I'm just gonna log the error and then we'll make an otherwise statement. We're going to render the index file located in our views folder, and we're going to pass an object. So this is what we're going to be sending back to the view so the key can be anything to make it simple to understand, will call it notes, but it's always gonna be whatever this is. So right now we're calling it results as faras, the second parameter of the callback. Four are a synchronous parallel method, so we always use whatever this second argument is, and then the number of the index over the array. So this zero represents the first function that we defined up above and users and the second set of results will set to users. And it's going to be the second function that we've defined, which grabs all of the users. So go ahead and make some semi colons here and save this first thing is to check to see if this crash and it didn't and second thing is to check to see if it worked. So let's go back over to my local host 80 80 and refresh the application, and we get what we expect. We've been able to retrieve all the our users and display them within this input box field , and we're also displaying a note which, with our user with the project and displaying what we submitted to our database. And let's just take one more look at our index dot html so you can see we're basically iterating over note in notes. So again, this notes represents what we've defined in our a sink parallel. This is very angular like so this is note in notes. And then we can preface everything with notes dot the property of our database, and then it displays just like that. Now, the last thing that we want to do in this application, if we want to filter the notes. So when we hit this button, I want to filter for who has submitted the notes. Right now, if I click Mary and I hit filter notes, it just goes to a cannot post field. So we'll fix that in the next video 9. Filter by Member: Hello, guys, and welcome back to the final video of our meeting application project. In this video, we'll see how you can filter for the users and display them on the index page. So right now, I'm in our index dot html page and I'm about halfway down the page and we see this latest notes area, and I have a comment filter list by member name, and we're making a post method based on which user we've selected. So right now, if we look at our virtual meeting notes, I can select one of these users. But if I try to filter, it's not going to work. So let's fix that. And the first thing that we need to do is create a new post route, and we'll be using the same location as our route. Of course, so we can say writer that post, and it will be at the index location. We're going to be creating a new controller method in our notes controller. So we'll say notes controller, and we're going to Neymar method notes by member. So that's it. I'm going and save this file, so I'm going to go into our notes, Doc Controller dot Js file and I'll go ahead and put this below our create notes method. We'll scroll to the bottom here in a leave a comment right here. So we want to make sure that we're filtering by name and we're going to export our method, which is going to be called note by Member, and it's going to equal a function. Of course, that takes a request in response. Object at the very top here. I'm going to define two variables, one which is going to grab all the notes so I can save our query, who's no doubt find and one that's going to act as a filter. So far, Filter is going to equal. Request the body that member name because that is what we're filtering. Four. So we'll start off with an if statement if there are known users with any notes created so we can say if filter dot length triple equal zero. I'm just going to print something out to our consul, saying no notes found, and otherwise we're going to return the notes for the member we specified. We can use that by saying query that where and passing in member name with the filter so you can see here we're using a new mongoose method, and this method is called Where? So let's check that out. I'm gonna open up Armand Goose docks. And so this is Margo, Starcom slash doc slash queries dot html And I'm gonna scroll down a little bit and we can see a couple of examples where where is being used so we can use where to grab all the documents with whatever it is that we specify. So it's a really handy function for Mongoose. So again, we can say where member name equals the filter. So if we're passing in Joe or Marry or John, it's going to return all of the documents with that user defined in the note. So after we get back all the notes, I'm gonna head it and sort them and let's sort them by the created on date, and we'll make sure that we sort it by descending. And the last thing that we need to do is we don't want to forget to execute this. We need to say, execute passing a function with an air handler as well as the results. And just like before we're going to render the results within the index page, and we're going to send back the object of notes with the results. Make sure that I have my semicolons here, you know, save this. And now hopefully our filter functionality is working. Don't go back over to my local host. 80 80. I'll check my costal to see if there's any errors, and it looks like we're good. So refresh my up and I'll choose Mary here and I'll Click Filter And right here we see note from Mary for the project, and I've only added one so far. So that's why we're only getting one results. Let's go ahead and add one more note for Mary, and hopefully we can see to results good in saving, you know here and we get sent back to our index page. We'll click on Mary and I'll click filter notes and we get the two notes for Mary, and you can see that we're filtering by date because this is the newest note that we have submitted