How To Build A Markdown Blog Using Node.js, Express, And MongoDB

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
I hope you're ready because in this video we're gonna tackle how to build a blog using MongoDB Express and node and by the end of this video the skills that you learn are going to be applicable to absolutely any application that you want to build with these technologies so let's get started now welcome back to web dev simplified my name is Kyle and my job is to simplify the web for you so you can start building your dream project sooner so if that sounds interesting make sure you subscribe to the channel for more videos just like this one now to get started I have a blank folder open and Visual Studio code and then the final version of our project open on the right hand side of our screen so we can see what we're going to build and as you can see we have our different articles showing up on our main page if we click read more we can actually view our article and the great thing about these articles is if we click Edit you can see they're actually written using markdown so we can change this markdown to have anything we want let's just say we wanted to add a smaller title in here we could just say pound pound small title and click Save and you can see we have our smaller title after a bigger title so our markdown is automatically being converted to HTML we also have the ability to create a new article type in some stuff here and you see it shows up and even the path to our article takes them to account the title of the article instead of having some ugly ID in the route so we have all of this interesting stuff baked into our system even including delete buttons so absolutely everything is here and I'm gonna show you how to build this from beginning to end but the first thing we need to do is actually set up our server if we type NPM omit - why in our console hit enter this is going to give us a boilerplate basic package JSON and now if we type NPM I and all of our different dependencies we can install our dependencies so we're gonna have Express we're gonna have Mongoose and we're gonna have each AS Express allows us to create our server mongoose is for our database and ejs is for our different views next thing we can do is install our dev dependencies so we'll say npm i - - save and in here we want to install node Mon now node Mon is going to allow us to automatically refresh our web page every single time we make a change to our actual files here and in order to run node Mon we're just gonna create a simple script we'll just call it dev start and inside here we're just gonna put node Mon oops server je s and now if we create that server dot je s file and we run NPM run dev start what's going to happen is this file server jeaious is going to be brand and every single time we make a change and click Save you see it's gonna refresh we're getting an error obviously because this is not real code but as you can see everything is hooked up correctly now the next thing to do is to create our server so we're gonna get expressed from that library that we just installed so we're gonna require Express and we're also gonna get our app variable and that just comes from calling Express so as you go to say Express and call it as a function like that now if we do ab dot listen and pass in a port we can start up our application and it's gonna be on port 5,000 so now if we go to our browser and type in whoops localhost port 5000 you can see we get our application loading up and it says cannot get slash and that's essentially saying we don't have a route set up at the index so let's create that route we're gonna use app to do that I will just say app dot git and we pass in slash here which is just our index route our main route and this is going to take our request as well as a response and for now let's just send to the user with our response dot send the text hello world and if we save refresh you can see we get the text hello world being printed out to our screen so we know that everything is working properly we have our view hooked up but now it's time to actually make it so it prints out HTML to the screen because just printing out text is not very useful so to do that we first need to set our view engine will say app dot set put pass in here view engine and we want this to be set to ejs and that's because we're gonna be writing all of our views using ejs and then our view engine is going to convert that ej code to HTML so once that's done we can create a new folder we're gonna call this views and in this views folder we want to just create an index ejs for now and inside of here if we click exclamation point hit enter or tab this should bring up this bullion plate code for you we'll make our title blog and then inside of here we'll just say this is HTML so now in our server instead of sending we want to call render this is going to access our views folder and we just pass it the path to the view we want which in our case is just called index now if we save refresh over here we get our HTML and it says this is HTML we can put this inside of an h1 to really prove that this is HTML now if we save and refresh over here you can see it says this is HTML so we have everything working exactly as we wanted to so now with these basics set up we have a bunch of different routes we need to create we need a new route we need to be able to view an actual article delete an article edit it save it all of that different stuff and instead of putting all of those in this server JS file because it would become quite large we're actually gonna create a new folder which is called routes and this is where all of our different routes are going to get stored to and for now we're just gonna create a route called articles J s just like this and then here is where we're gonna put all of the routes directly related to our article so for example our show route here our edit route all of that is going to be inside of this articles J s and in order to use routes in here we first need to set up or Express so we're gonna install that Express variable again by just requiring Express and then what we want to do is get our router and this is just equal to Express router so if you say dot router and call this as a function this is going to give us a router that we can use to create views and just like this where we say dot get and then render something it's gonna give us that exact same capability but it's gonna be through this router instead so we could say router get and pass in a slash like this and now we're going to get a route at the slash but the main thing about this router is that we actually have to tell her application to use this router so in order to do that to export this router from our articles yes so we can say module dot exports is equal to our router and now wherever we require this file we can actually read in this router so if we go into our server we can just require our router by coming up here and saying Const article router is equal to require and we just want to put in here dot slash that's going to be a relative path so we're going to go inside of our routes folder and then we're going to get articles J s out of there so now we have our article router which we created in this file and now we have access it to it in our server j s and what we can do is we can tell our app to use that router so we can say app dot e use and we just want to pass in our article router but we also need to tell our article router where it's going to be based on because if we look over here we click read more you'll notice in the URL it says slash articles when we click Edit it says slash articles everything has slash articles in front of it so we need to say is we want our article router to be at slash articles like this and now what's going to happen is every single route we create in this article router is going to be added to the end of slash articles so if we come in here and we say router get and which is just gonna be at a slash and we want to pass it in our request whoops request and a response and for now we'll just say res dot send in articles you may think if we just go to our slash route it's going to render in articles but if we go over here and do our slash route it's still rendering this is the HTML from here and that's because everything is added to the end of slash articles so we need to go to slash articles and then if we get the route at slash articles just the index route it's going to render out in articles so everything in here is going to be relative to that path if we say test here for example we would need to do slash articles slash test and if we save this refresh over here you can see that that now is showing up properly so just remember everything in this is going to be based on this slash articles route so we just need to know that we don't need to include that here now before we start diving into a bunch of really complex routes for our article I first want to get our main index route finished out this route right here so in order to do that inside of our server we're already rendering our index we want to be able to pass all of our articles to this index because if we come over here and we look we have all of our different articles on this main index page so in order to do that we can just pass an object to our render and we'll say articles and we're going to pass it our articles and what we do here is we just pass any object we want with any keys any values and this is going to be available in our index tjs so we can actually render out that article so I could actually change this here instead of rendering article we're just going to render something called text so you just need to use a less than symbol and then a percent symbol and then the equal sign and this allows us to output a variable so this is going to be a JavaScript variable from nodejs that we output and we're just going to call it text now in our server let's just put text is equal to hello now if we refresh you can see the text hello is being prepared on our screen because we're passing it from our server into this ejs and this nice little bracket syntax allows us to actually output that to our screen so now instead of passing just simple text let's actually pass our articles and for now we don't have any articles so let's just create a variable called articles and we're just going to set this to an array with one object in it and we're gonna create our own article to start with so now let's go look at our blog and see what we need we need to have a title a date so the date that we created this add as well as some form of description for each one of our different articles so we know that we want to have our title we're just gonna call this test article we're gonna have a date that we created this article ad so we're gonna say created ad and we'll just set that to date dot now that's the current date and then we're also going to need to have a description we're going to set this to test description so now we can pass these articles to our view and now instead of our index tjs we're gonna have access to a variable which is called articles just like this so we can actually iterate over these articles and do whatever we want with them so now the next step is going to be to create our index page so it looks just like the index page that we have over here and in order to get all of these nice styles that we have we're going to import a library called bootstrap if you just type in get to bootstrap calm you're gonna be able to find this link that just have it on their website you can copy this over and it's gonna give us access to bootstrap which allows us to style everything really nice and really easy the next thing that we're gonna want to do is create a div and inside this div we're just gonna have a class which is going to be called container this is a bootstrap class which will allow us to have this nice little padding around everything in our application next we're gonna have an h1 this is just gonna say blog articles just like that and in order to give it space between this text and our button down here we can just give this a class which is margin bottom of 4 this is just going to give us a little space on the bottom next we're gonna have that link which goes to new article for now we don't actually have a new article page but that will be at articles slash new when we do created so we can just type in that href and we also need to give this a class of button and button success that'll give us that green color button and we can just type the text new article just like that now if we save refresh over here you can see we get our blog articles as well as our new article button when we click it it obviously doesn't work because we don't have that route created yet but we will get to that later now the next thing to work on is each one of these cards for our article so in order to go through each one of our articles we can actually use this same less than n percent symbol but if we don't put equal we can still run JavaScript code it just won't be outputted to the page so we could say articles dot for each and we want to run a function here which returns our article so now right here we're running this for each function and we're going to make sure we close this off just like that so now by putting this inside of these less than and percent symbols we're running this for each code and then for each iteration of our article we're gonna output some type of HTML here so we're gonna have a div which has a class of card and we're going to put some margin on the top of 4 close that off and inside of here we're just put the text for now which is just going to be equal to that article dot title this is just to show you how this is working so if we save and refresh you can see we have a card which has our test article because it's looping over all of our articles if we were to add another article to this list if I just copy this down and we want to have a test article too with a test description to save and refresh you can see we now have two cards one with our first article and one with our second article so it's just looping through and printing out this set of HTML for each one of our different articles so obviously we want to do more than just put the title in here so in order to do that let's put another div this one is gonna have a class of card body just like this whoops card body and instead of here we're going to have all of our different text for our title as well as our description and our created ad so in order to do that we're gonna need here in h4 with the class of card title this is where we're gonna put the title for our card which in our case is just gonna be article title just like that close that off and then we're gonna want our subtitle which we can just put inside of a div so we can say card whoops subtitle and here we want to have some text muted class this is going to give us this grayish color that you see on the right side of our screen also we're gonna want to come in here and put some margin on the bottom will say mb2 and inside of here what we want to put is our just or created at so we can say article that created that and if we save this and look at what this looks like right now and you're gonna notice something are created at is just a timestamp it's just a random bunch of integers that don't really mean anything so in order to convert this to an actual string we're gonna use the function to locale date string and now if we save and refresh you're gonna notice that we get an error and saying that this to locale string is not a function so if we go into our server the reason for this is that we actually need to create a new date instead of using date now so we can just call new date instead and now if we save and refresh you can see that this actually shows up as a date which is what we want if we were to get rid of this to low-cal string and look at this again you're gonna see we just get this really jumbled up a really long date string which we don't actually want so that's why the two locale date string is converting this to whatever locale here in so for me this is American so it has the month first and then the day but depending on where you are it could have the month second and the date first if you lived in Europe for example now let's look back at our blog and we can see the last things we have left is the description and then all of these different buttons so let's do our description next we can just say we're gonna have a div here which has the class of card text we'll put a little margin on the bottom to space it out from our buttons and then we can just render inside of here the text article description just like that and now save refresh over here and you'll see we have the description showing up inside of our cards and now next is going to be these different buttons but for now I just want to skip these buttons because we really need to work on getting our new article working first before we work on viewing editing and deleting articles because right now these articles don't exist these are just placeholders so we don't really need to create buttons for them yet so the next thing that I want to work on is creating this new article route so inside of articles j/s we can create a route which is just gonna be add slash new and here we want to render a page which we're gonna put inside of articles the way I call this new so now if we open up our views folder we can create a new folder called articles and then inside of this folder we can create a view called new ejs and I actually want to move this index ejs up into this articles as well because this is really the index view of all of our articles so that means on our server we want to render articles slash index instead of just slash index if we save refresh everything is still working the same as before it just makes more sense to have this index tjs in our articles folder since it really is just rendering out a list of articles now we have our new route set up and we have a file called slash new so let's just copy everything from our index tjs into our new for now and we'll just delete everything inside of here except for our container because we want to keep our container and if we save we'll just put some placeholder text in here and click a new article you can see we're going to that page with that placeholder text so we've hooked up our view to our route properly at articles slash new now inside of our container we can just create a simple h1 which is going to be our main header we're gonna give us some margin on the bottom will say margin bottom four just to space it out from the form that will come below it and if we look at what we're building it's going to be this exact form over here so we can use the text new article inside of our h1 just like that so now over here we have this new article text showing up and the next thing we need to work on is creating out our form so let's come down here we're gonna create a form we need to specify an action for our form and we also need to specify a method for our form and then in here we're gonna have all of our different inputs so our method is going to be post because this is going to be a post request because we're actually trying to create something and as for our action we're just gonna go to slash articles whoops slash articles like that so that means in our articles j/s here we're gonna have a router dot post which is going to go to just this slash wrap like this now we're gonna have a request and a response so whenever we submit this form it's gonna call this router dot post which is at that slash articles which we know is this slash route inside of our articles router so now back into our new here we can work on creating all of our different inputs but instead of creating our inputs directly here inside of this form I know for a fact that our new article inputs as well as our article edit inputs are going to be exactly the same so we actually want to create one single file where we put these inputs so we don't have to copy it between our new and our edit view so to do that what we're gonna do is create a new file inside of here and we're just gonna call this underscore form fields ejs you don't have to put the underscore in front of the name but since this is going to be a partial view essentially it contains only these input fields and nothing else I like to start it with an underscore so it's really obvious that this is a partial view and not a full view now in our new EGS we can actually render this in we used less than plus the percent symbol followed by a - this is going to allow us to render actual HTML instead of just rendering out text so this is going to render the exact HTML inside of form fields ejs and we can just say include which is going to allow us to include a page and we just want to type in the path which in our case is form fields because it's in the same folder and we'll close this off with percent greater than symbol so now if we save this type some stuff in form fields and refresh over here you can see everything in the form fields is rendering on our page because of this includes statement so now we can actually go ahead and start rendering out our different inputs in this form fields file so the first thing we're gonna do is create a div with the class of form group just like that and then inside of this div we're gonna have a label this label is going to be for our title element and we're just going to put the text title inside of it we're then gonna have an input which is just a type of text for our title it's gonna have a name which is title and it's also gonna have an ID which is title which way our label and our ID for our input or hooked up together now if we just save that and refresh over here you can see we have our nice little title input which looks pretty good but in order to style this with bootstrap let's just add a class which is form control hit save and refresh and now it's styled perfectly the bootstrap so we have this nice input just like we do over here one other thing that I want to do is I want to make sure that I mark this input as required so that when we try to submit the form it's going to tell us that this field is required which is going to be exactly what we want so also let's come down here and we're gonna create a submit button so let's just create a button which has the type of submit and this is going to have a class which is BTN and BTN primary which would give us this nice submit looking button and then for our text let's just put save and if we refresh and we click that Save button you see we're gonna get the error because our title is not actually filled out which is exactly what we want and also let's make sure that this Save button is not inside of our form group we want this to be separate from our foreign group and that's just going to give us that nice spacing which is exactly what we want now let's copy this form group down because we're gonna do almost the exact same thing for our next section which is going to be far description let's just look back over here we're going to have our description section next so we want this to say description we want this to be a text area so we're going to use text area instead and this text area is going to have a name of description it's going to have an ID of description just like that and we also want to make sure we give it that same class which is going to be formed control so we can get rid of this input now and save refresh over here and now we have our description text area where we can put multiple lines of content if we want now lastly we're gonna have our final section which is going to be our markdown section so we're gonna say for markdown this is gonna say mark down names gonna be markdown ID is marked down and that same form control class is going to apply and if we refresh we now have the section far markdown as well lastly I want to put in here a cancel button so this is just gonna be an anchor tag which 1/8 ref that goes back to our index page so this allows us to go back to our index page and cancel and we're gonna put in here the classes of BTN and BTN secondary which is gonna give us kind of a nice grayish color and if we just type in the text cancel hit save refresh you can see we have our cancel button which brings us back to our home page and then our Save button which is going to call our article CAS right here inside of this post method so now our next step is to use this post method to save this article to our database so we actually need to hook up our database to our application to do that we're gonna go back to our server jas file and we're gonna call here Const Mongoose is equal to require and we want to require that mongoose library just like that and using this we can actually connect to our database by just calling mongoose dot connect and we want to pass it in a string to our database which is gonna be MongoDB colon backslash backslash like this localhost and then we just want to put in the name of our database this can be whatever you want I'm just gonna call ours blog and now with that single line we're connected to our database if we click Save you can see we're getting some deprecation warnings down here essentially what that means is certain things are going to be removed in the future so it's saying it recommends us to use the new parser so it wants us to pass this extra option to our connect function just like that so now we have our used new URL parser being passed in there if we save we now are left with just one deprecation warning which is to use unified topology so we're also gonna pass that in so let's do that just like that and now if we save you can see our deprecation warnings are gone and we're properly hooked up to our database you may have different deprecation warnings or none or more it really depends on the version of MongoDB that you're using and the version of Mongoose that you're using so really just do whatever the console tells you to do based on your different warnings so now that we have Mongoose setup the next thing we want to do is to create a model which is going to be where we store our articles so let's jump over here and create a new folder we call it models and in this folder we're gonna create an article j/s model and in here we're gonna use mongoose so it's import mongoose by just saying require of mongoose just like that and what we want to do is create something called a schema so we're gonna create an article schema and this is gonna be equal to new mongoose dot schema just like this and in here we just need to pass it a set of options for all of the different columns our article has so we know we're gonna have take title and we specify all of the different options for our title inside of an object so it's going to be required of true since we want to always require this and we also want to specify the type which is in our case going to be a string so we're gonna have a required string title next we're gonna have our description which in our case is gonna have a type of string and it's not even gonna be required we don't always need to have a description and then we're also gonna have our markdown and in our case our markdown is going to be a type of string and we want to make sure that our markdown is also required so we're going to say required of true now lastly we want to have the date that we create this app so we're gonna have a created hat and this is going to be a type which is date and then we can also specify a default and this default is just going to be date dot now and a default takes a function so we can pass it a function like this which is going to call date dot now or we can just call it our date now function like this without the parentheses and it'll pass this function and call this function every single time we create a new record so essentially by specifying our default every time we create a new article if there is no created at is just going to give it to the current date as the create at that time which is exactly what we want now in order to use this article schema we need to export this by using module exports and we need to call Mongoose model and here we pass in the name of our model we're just gonna call this article and then we pass it in our schema which is our article schema so now we have a table in our database called article with all of these different columns specified for it so now in our article route here let's import that model we just created when I call it article is equal to require we're going to use that dot slash trick then we're going to go back one directory so that we can enter our models directory and get out our single article model so now we can create a new article and we'll say article is equal to new article and in here we want to pass it all of our different options but in order to access the options from our form here inside of our post request what we needed to do is we need to tell Express how to access them so in our server we just want to tell our app to use Express dot URL encoded and we can just pass it the option of extended is equal to false what this essentially is saying that we can actually access all of the different parameters from our article form inside of our article route right here by just accessing request dot body and then dot whatever we called this so title for example or description or we could even do markdown we can access everything from our form on that request dot body object so let's set our title to request body title then we're gonna do the same exact thing for our description so we can just say here description and lastly we want to do markdown so let's just copy that over to our title and now we've created a new article with a title a description and markdown based on the exact specifications of our form over here and now we can save that article by calling article dot save and this is an asynchronous function so we just want to make sure we set this up inside of our own async function and we await this article that save and this is going to save our new article and if you're not familiar with async await I have an entire video on it linked in the cards in the description down below that you can check out so now that we have that let's make sure we wrap this now try-catch and in our catch we want to just catch our error and if we for some reason have some kind of failure for example our title is not specified or a markdown is not specified it's going to throw an error here which we can use to return to the user and tell them that there's some type of problem with their article saving but if our article does save properly it's going to return here so we can update our article variable with the new saved article this is going to give us an ID for our article and then we could just say res dot redirect and we know how to redirect our user to our articles slash and then we want to redirect them to our article ID for now so we can just say inside of here use these as backticks instead that way we can use string interpolation we can just say article ID so we're going to be redirecting them to a page that is at slash articles slash ID so let's create that route real quick we'll say router get as you just gonna be slash ID just like that I'm just going to take a response I'm sorry a request and a response just like that and every time we pass in some kind of route that has articles slash something if it's not new it's gonna go into here as this ID parameter so essentially redirecting the user to this router but if we have a failure we want a res ender and we want to render out our page that we were just on so we're just gonna say articles slash new and we want to make sure that we pass in our article that we had before so that way we can pre-fill all of these different fields with the article information they passed in previously so now let's save that and let's do an article that we know is gonna fail we can put a title in we can put a description but with no markdown this is definitely gonna fail so if we click save you notice that we get an error though and if we scroll up here little ways we can read what our error is which is saying unhandled promise rejection cannot read property title of undefined so it's saying that it cannot read request body dot title because body is undefined and this must be because our URL encoder for express is not properly working and the reason for that is because we're using our slash articles route before we're setting our URL encoder so this URL encoder needs to come first above our slash articles let's actually just take this slash articles move it all the way down to the very bottom so that we know it comes after everything else and now if we save and we actually just refresh our page over here you should see that it failed which is exactly what we wanted it brought us back to this page but everything is err it out you see this title is blank the descriptions blank this markdowns blank even though it should pre populate with the values of our article so if we go back into here we're passing an article down to our articles slash new so we can actually use that inside of our article slash new inside of our form fields and we can set the default value of every single one of these to equal to our article title for example and now if we type in a title and it's safe you can see our title is pre populated based on what we had inside of our article dot title let's do the exact same thing but for our description so we're gonna do it instead of here but instead of putting it inside the value we need to put it inside of the text area itself so we can just say article that description close that off and we'll do the exact same thing for markdown we can say article dot mark down close that off and now if we type in a title description leave our markdown blank so that we get an error and we click Save if you see it prepopulates all these values but we will run into a problem if we just cancel out here and click new article we're gonna get an error and that's because we never pass article in when we just do our normal slash new route so let's make sure here we pass in an article now we're just gonna make this our new article so this is just a completely blank default article now if we refresh you can see everything works because we have access to this article inside of both our new route as well as this route where we render our failed article as well now in order to prevent the user from actually submitting a article that is not valid we're gonna go into our form fields and make sure we specify our markdown as required now if they try to save something that has a title and description only if we refresh this click Save you see it forces them to fill out this markdown section and now if we fill out this markdown section click Save you see again we're getting an error this markdown is not properly being sent to the server so let's see exactly what that error is if we go over into our article j/s we look here we're sitting in our markdown to our request body dot markdown that looks correct let's go over here we have our markdown being parsed right here that's correct that's correct all of that looks good so the next step we can do is to print out the error that we're getting to see exactly what our problem is we can just say console log of E now if we save type in something for our markdown hit save we can see down here assignment to constant variable @ blah blah blah blah blah is not working and that's because I made this article eight constant and then I tried to reassign it down here so let's make this a let variable click Save try to create our full thing with title description and markdown click Save and you can see that it's rendering properly you see it's just loading forever and ever and ever and that's because this route doesn't do anything yet so inside of this round pushes say res dot send request dot params ID this is gonna be the ID of our newly created model now as you can see it's rendering out that ID to our page which is the same ID that's in our URL up here also one thing I want to do is I noticed that when we had failures with our markdown it wasn't being persisted so let's go back to our form fields take a look at our markdown section you'll notice I'm missing this equal sign here which is why our markdown was blank every time we had in hair now with that fixed if we have an error this markdown section should be properly propagated so we can actually see what's going on now back inside of our article jeaious what's actually make this route a hundred percent work the first thing we need to do is to get an article and we can get that by calling article dot find by ID we can pass it I request grams ID and now we have access to our article and instead of just sending we can actually render out our new page so we'll say render we want to render slash articles slash show which is going to be the page that shows our articles we're just going to pass it in the article that we just created by querying our database but this article that find by is an asynchronous function so again we're gonna use async and we're gonna use a weight here to make sure we wait for this article and before we actually render this article we first need to check if our article equals null essentially if we cannot find an article we just want to redirect our user back to the home page so if for example I go to slash articles create a new one and I instead have a wrong idea up here I just changed this B to a C and hit enter we get pushed back to this home page instead of actually having our articles show up and be rendered on the page and correctly we just get pushed to the home page saying we cannot find what you're looking for which is exactly what we want so now let's go ahead and make this articles the slash show page because right now we don't actually have an article show page so in our views in our articles folder we're gonna create show ejs and in here let's just copy over will be having new for now paste it in to show and we'll get rid of this form because obviously we don't want to form and for our title we're just gonna have the title of our blog so we can say article title just like that and now if I save create a new article and click Save we got brought to the article and you can see we have the title showing up on the page which is exactly what we want the next thing I want to do is slightly reduce this margin on the bottom of our title so that way when we put in here are created at section which is just going to be article created at dot to locale whoops date string when we create this section it's going to be pushed up really close to our article title which if we refresh here you can see just like that and I want to just add a few classes here we're just gonna add that text muted class so that way this is gonna be great text if we refresh you can see it looks kind of grey and also I'll say margin bottom of two so that way we have a little bit of space on the bottom for when we put our button because if we go over here click on an article you can see we have our are all articles button right here so we're gonna create that all articles button this is just a simple anchor tag which goes to the index page and says all articles that we want to give it a few classes we're just going to give it a class of button and buttons secondary just like that and we'll copy down this again because we're gonna have a route to our edit page which is slash articles slash edit and we want to pass in the ID so we're just gonna come in here and say article ID so now we're going to our edit page with a specific article ID and we're gonna make this an info button which just says edit now if we go over here refresh we now have our two buttons showing up exactly like we want the last thing that we need to do is to actually render out our markdown and instead of rendering this as HTML yet we're just gonna render it as just plain markdown exactly as they typed it into the text box and then later we're gonna come back and actually render it as HTML so we can just put inside of here our article dot and mark down and if we save refresh we now have that markdown showing up exactly as we want and we're just gonna wrap this inside of a div that way it's gonna be on its own line and if we refresh there we go we have our markdown right there so now with that done let's go back to our all articles page and actually make this work instead of using just test data so let's open up our server dot j s and inside of here we're gonna remove these test data for our articles and instead we're gonna set our articles to a new variable and in order to access our articles we need to pull in that article model so we can just say article is equal to require we want to do dot slash models slash article and now we can call article dot find this is gonna get every single article and again we need to make sure that we await this function because it's asynchronous and now if we save and refresh we now have all of the articles that we've created so far during this video one other thing that I want to do is actually sort these articles based on when they were created at and I want to make sure that the older articles are showing up at the bottom and the newer ones are first so we're gonna sort in descending order and if I save refresh you should now see that the very first article that we created is all the way down here and the most recently created article is all the way at the top if we create a new article and we'll just call it top this should be our very top article and as you can see it is the very top article based on how we are sorting which is exactly what we want so now the last thing to do with this index page is to add in the button for our show so we can actually view each one of these individual articles so when our index page let's create that show button we can just do it right below this div for our description and in order to access this we just need an anchor tag this is going to go out to particles and here we want to pass in the article dot ID and then we can just say read more and we're going to give this a few classes so it's easy to read and look good so we'll say button and we're gonna say button primary now if we save refresh we have our nice read more button just like we do over here and if we click this you can see it brings us to our article and each one of these is going to bring us to the individual article for that button which is really really good now the next thing that we need to work on is going to be actually making it so that our markdown renders properly and also so that we don't need to use IDs up here anymore because these IDs are really ugly so instead we're gonna use what's called a slug which is just a version of our title which is going to fit in the URL so to make all of these changes we're actually going to modify our models folder here and inside of here we're gonna import quite a few new libraries so let's just stop our server real quick and we're gonna NPM I some new libraries we're gonna do a library called the marked as well as a library called slug of I and this marked library what this does is it allows us to create markdown and turn it into HTML and if I just allows us to convert something like our title into a URL friendly slug which we can use instead of our title so now that we have those let's get our marked here which is required of marked now we also want to get our slug of AI which is just going to be here equal to require of slug of Phi just like that and the first one I want to start off with is slug of Phi because this is quite a bit easier than doing our markdown one so now we're gonna create a new column for our slug this is going to be a type here of string this is going to have a required of true and we're also going to make sure that this is unique so we're gonna put unique of true as well this will make sure that we can't have more than one of the same slug since we're using this in our URL if two articles had the same slug then we wouldn't be able to tell which one is which from the URL alone and the reason I'm actually putting this in the database is so that we don't have to calculate this every single time we want to access an article we just calculate it once and save it in our database and never have to worry about it again but in order to automatically calculate this every time we go to save our article we can actually set up some validations and some before attributes so we can say article schema that pre and if we want to do something prevail a date so we're gonna run whatever function we pass to this pre right here this function just like this we're gonna run this function right before we do validation on our article every single time we save update create delete any time that we do any of those things this function is going to be R in and what we can do in here is create our slug from our title so we can just say if this dot title then what we want to do is set our title so we can say or set our slug I'm sorry this dot slug we can set that equal to a slug of Phi of this dot title and we want to pass a few options first option is we want to make sure we convert our slug to be in lowercase and we're also going to pass in the option of strict true and what this is going to do is this going to force our slug a fight to get rid of any characters that don't fit in a URL so if we create a new article that for example how to : instead that is actually going to be removed by this slug of Phi here when we have strict of true and you'll notice that when I tried to access the new route it gave us an error which need to start our server backups will say npm run dev start and as we can see our service started up we can go to new so if we had a title that had like a colon in it this strict true is just going to remove that for us which is exactly what we want also something important is this function takes a next parameter and we just need to make sure we call next otherwise we're going to get errors with our validation so just make sure that next is in there and now we've set this up so that we can create a slug from our title every single time we validate a model so now if we create a new article for example we'll just call this test article we'll even put a colon in there and just test and now if we click Save we have our test article test but instead of using our ID up here we want to use our slug so let's make a few changes to the rest of our page instead of our routes here instead of ID we want to use slug and instead of finding by ID we just want to call find and in here we can find by the slug based on our request dot prams slug so we're just an articles defined for an individual slug instead of for our ID also when we create a new article we want to route to the slug instead of routing to the ID so now if we refresh this we should get an error saying that it's not working because there actually is no article with a slug that looks like this so let's go back all the way to all of our articles we have our test article here and in order to get our read more button to work if we just go to our index tjs instead of using our ID let's use our slug here click Save and now when we click read more we're getting a new error and the reason for this error if we go back to our article that Jes here is that this article dot find actually returns a array and we want to find just one individual article instead of an array of articles so now if we save and we refresh you can see that we've probably got our article and you can see our route has test - article - test and that's because it's slug of fine this title right here so now we have really good looking URLs instead of the ugly IDs but you will notice we got a new deprecation warning which says collection and share index is deprecated use create indexes instead so let's just copy this create indexes go back to our server j s and we just want to pass that create indexes as true to our Connect right here and we just need to make sure that this actually says use create index and now if we save you could see that that deprecation warning goes away and this is something that when I was originally doing this I just had to Google this error to find out exactly what it was and I found that I just needed to use use create index true and that got rid of the deprecation warning and depending on your MongoDB version like I've said you may not run into this issue so now we have these nice test article tests working with our slugs if we go back to all articles and we try to click a different article we're gonna notice a problem it doesn't actually have a slug and that's because these were all created before our slug code was added so let's actually work on creating that delete route so we can delete all of these old articles that we created that don't have slugs and we know it won't actually work so back into our article dot J s we need to create a new route for deleting so we can just say router that delete and this router dot delete is just going to take in here an ID and then we're gonna have our request and response just as always and let's just already make this an async function since we're gonna need to delete articles which is asynchronous and we can just call the weight of article dot find by ID and delete we can just pass in the request Rams ID so this is gonna find an article by the ID and delete it then we could just call res that redirect back to the home page and that's all it takes to create this delete route but creating our delete button is a little bit more complex because in order to call this dot delete version of our router we need to have an action of our method which is going to be equal to delete and a link only does get and a form will only allow us to do post or get so in order to actually use delete as a method for our form we need to use a library called method override siliceous close out of this and p.m. i and we want to install method override just like this whoops spelled that wrong method override there we go and what this is going to allow us to do is actually override the method that our forum passes so we can do delete or we can do patch or put instead of being stuck with get and post so now in our server let's make sure that we use that so we can say Const method override is equal to require of a method override and then we just need to tell our app down here to use that so we'll say app use method override and we want to pass it the string for what we're gonna use we're just gonna use underscore method so now whenever we set the parameter underscore method in any type of form situation this is going to override the method so if we pass underscore method of delete it will allow us to call this delete router right here and I'll show you that just now instead of our index tjs so normally if you think of a link you would think we need to have an anchor tag with an href but that's going to be a get route and when Google crawls your site they click every single link tag so if you're using a link tag for deleting your routes and your articles every single time Google indexes your site they're going to delete everything in your database you definitely do not want that instead we want to use a form and this form is going to have an action which is slash articles and this is going to have at the very end of it our ID so we want slash is going to be article dot ID and then we want to make sure we include that method override by same question mark underscore method and then we want to set that to delete so now our method is gonna be overridden with slash delete and we also just want to set the method of our actual form to be equal to post just like that and now in our form all we want to do is have a single button so we're gonna have a button which is going to have the type of submit and we want in here have some classes will say button and we'll say button danger and we'll just say delete now if we save refresh you notice that we're site is not working your NPM run dead start that should start up our site and now you can see we have a relief button as read more button you will notice that our delete button is not next to I read more button though so instead of our form we can just put a class which is D in line and that will just change our form to be an in line and there we go our delete button is right next to our read more button and if we click delete you can see it removed that top we removed that one we remove this one and every time we click delete it's gonna call and remove all of our articles so now we're just left with the only article that has a slug which is exactly what we want so now we have the slug portion of our article done the next thing to work on is our markdown portion we're gonna convert this to HTML but one thing we have to worry about is when we convert our blog markdown to HTML we need to sanitize that HTML so people can't add malicious code into our markdown and actually run JavaScript on people's computers we need to make sure we sanitize it otherwise people can just write any HTML they want and it'll run properly so we're gonna need a few more libraries for that so let's NPM I here and we're gonna use the libraries of Dom purify that allows us to sanitize our HTML and that library requires us to use je estan which is just a way for us to actually render a HTML inside of node.js because no jeaious doesn't really know how HTML works on its own so first we're gonna get our purifier which actually returns to us a function so we're gonna say it would create Dom purifier and then this is going to be equal to require whoops require Dom purify just like this and we're just gonna call this create Dom purify I think it's a little bit better the next thing we're gonna need is going to be our Jes Dom so that's going to be equal to require of j/s Dom and the reason we're putting in brackets like this is we only want the JS bound portion of what this returns so we're just gonna put it in brackets and get only exactly that portion of what we want next we can actually create our Dom purifier so okay Dom purify is equal to calling that create Dom purify function and this takes in a new Jes DOM and we want to in here just get the window object of our Jes Dom so this essentially allows our Dom purifier to create HTML and purify it by using this j/s Dom window object and all of this is in the documentation for Dom purify which is where I found all of it and where you can find it as well if you want to learn the degree of exactly how this works so now that we have our marked library which converts markdown to HTML and our Dom purify which sanitizes our HTML we can actually create a new column which is going to be for our sanitized HTML and in here this is going to be a type of string it's going to be required of true and that's all we need here so now we can say if this dot markdown then we can convert our markdown to sanitize to HTML so this dot sanitized hTML is equal to and here we just call marked with our markdown this is converting our markdown to HTML and then we want to sanitize that so we're gonna call Dom purify dot sanitize we're just gonna pass in our HTML from our markdown so what this does is it converts our markdown to HTML and then purifies that HTML to get rid of any malicious code that could be in there and to escape all HTML characters so now if we save and we create a new article and of course make sure we start up our blog so we say npm run and then start just like that so now we have our articles new we're gonna call this test test and in the markdown we're gonna have title so we have some big title and some random text and if we save you can see just right now our markdown is being printed out but if we go to our show EGS we can actually put in our sanitized HTML oops HTML and if we use that little - we can actually output raw HTML instead of converting it to a string now if we save refresh you can see our markdown has been converted to HTML we have this title as well as this asdf text so we know that this is working which is great but if we go back to all articles and view this original one we don't have any sanitized HTML since this article was created before we set up that pre validation so let's just delete this article for now so we have this one working article we can read more and see our information so now the last thing we have to do is take it our edit functionality because right now edit does nothing so inside of our article ejs let's create a new route for editing it's gonna be very similar to our new route so we're gonna copy that we'll say new slash ID because it's going to take in an ID and then we want to get our article which is going to be equal to a article that we actually find so we're gonna await article that find by ID of request dot params ID and make sure this is an async function and then we can just pass this article in here to slash edit so now we need to create a view called slash edit so now in our views we'll create a new file we're gonna call edit ejs and we'll just copy over our new into here and all we need to do is just change this to say edit article and we want this method here to have an override because when we actually supply our edit and we actually post that to our server we want to post that to underscore method is equal to and we want this equal to section here to be put that is essentially the HTTP method for updating something and we also need to make sure we specify that ID so we're going to put the ID in our URL here which is just going to be equal to article that ID there we go now if we save refresh you can see we get edit article as well as all the text for our title description and markdown but of course if we try to change this and hit save we don't have this put route setup yet so instead of our article let's create that put route we'll do it all the way down here we can say router that's put and this is going to be at slash and then our ID is going to be in here and this is going to take a request and a response and one thing to notice is that our post for created a new article and our put for editing an article are going to be almost identical so we're going to actually put these into a separate function this function is going to be called save article and redirect and this is going to take in whatever our path is whether it's edit or new so this is just going to be our path and then what this is going to do is actually return to us a set of middle middle ware so we're gonna return a function which takes request and response and this function instead of here is going to do a bunch of fancy stuff essentially everything that's inside of here is going to happen inside this function so let's just copy pretty much all of this down into here so we have an article being created we're saving that article we're redirecting if it was successful otherwise we're just putting them back on to our new page and we just need to make sure that this instead of being a new page is actually going to be for our path that we pass in to this method so here we're just gonna say path so this will be either new or edit and now instead of creating a new article inside of here we're just going to get our article from our request so we'll say request that article it's going to be equal to our article so we'll say what article equal request article and then we can say article title is equal just like this and we'll do this for our description whoops description and we're gonna do this for our markdown get all that on one line just like that remove these commas and now we have this function it's going to do all of this additional stuff that is essentially shared between our new and edit paths but how exactly do we use this let's go all the way up here to our new post route just right here and what we want to do is we want to add this after our function just like this save article and redirect and we're going to pass in new so we pass new to save article and redirect and it returns to us this function which is essentially a request response object it is essentially a type of middleware which is doing everything that we used to do inside of our slash post and now our new slash post all this is going to do is get our article and save it to our request so we can just say request dot article is equal to new article just like that and we already know that there's no additional information inside of here it's just our new article is going to be completely blank we're always creating a new one and then we need to call a next function so this has a next parameter and if we call next essentially what that says is go on to the next function in our list which is this save article and redirect so let's go back here at little base all the way back and first it looks like we have an error let's see what this says it says a weight article say a weight is only valid in a sinc function looks like I just need to make this an async function and now it looks like everything works so we can create a new article now let's create this with a title a description some markdown and save and you can see everything still works so what happens when we get to this post we're creating a new article saving it to our request calling next which essentially is the same as calling this save article and redirect and instead of here we have our article from our request and then we're just doing all the same stuff where we save our information and if we have an error agree to redirect them back to the page which had the new page so inside of our put here we need to do essentially the same thing we do up here with our post so let's copy this post exactly as we have it but instead this is gonna be Farah put and it's gonna have an ID instead of created a new article we want to await article dot find by ID and we want to pass it our request dot params ID and here if we want this to say edit because we're gonna redirect back to the Edit Page if there was an error so now we save click Edit let's change our title but test at the end of it and click Save and you can see that properly propagated we can also change this to be marked down and your markdown worked let's change our description to say test and now if we go back to all articles you can see that description was also updated so all of that editing is perfectly working and we're able to encapsulate all of that functionality into one single function which we share between our post and output to make our controller here for our routes so much simpler and easier to read now the last thing we have left to do on our index page is we just need to add a route for editing as well let's just copy over our slash articles grant changes to slash articles edit / articles that ID and in here we're gonna put the text edit and we're gonna make this an info button so it's just a different now save refresh and now we have an edit button and if we click this it'll bring it to the Edit Page change our text and it will update properly just like that and that's all there is to creating this blog if you enjoyed this video check out my other Express and note videos linked over here and subscribe to the channel for more videos just like this one thank you very much for watching and have a good day
Info
Channel: Web Dev Simplified
Views: 202,952
Rating: 4.9602857 out of 5
Keywords: webdevsimplified, express js, node js, node js tutorial, express js tutorial, express node js, express node, express node js tutorial, node js full stack, express js full stack, mongoose tutorial, mongoose node js, mongodb tutorial, mongodb node js, node js project, blog project, blog project node js, blog project markdown, markdown blog, blog tutorial, blog tutorial node js, blog tutorial express, markdown blog tutorial, node js express project, node js express mongodb
Id: 1NrHkjlWVhM
Channel Id: undefined
Length: 62min 27sec (3747 seconds)
Published: Sat Mar 14 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.