Node.js GeoJSON API & App | Store Locator

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] this video is sponsored by Ella node anyone can build on the node whether you need a development portfolio to land your next job or you're ready to put your app into production lonoa can get you there for $20 in free hosting credit click the link below or sign up at lynda.com slash traversée hey what's going on guys so in this video we're gonna build a full stack application using node Express MongoDB and Mongoose and on the front end we're just using vanilla JavaScript with a library called map box so basically we're gonna have an API that serves locations using geo json data so geo jason is a format for storing geographic points so in our model we'll have something like this a location field with type point and coordinates which will be the latitude and longitude we're also going to create a geo coder so that we can add a store so if we go to this page we can add just a regular address and it will geo code it and get the latitude and longitude for us so you can see I have some stores placed here so it's just a store ID and just a little icon and then if I go and add a store let's say zero zero zero six and we'll put this one in let's say 10 Main Street Haverhill mass and I don't even need the zip code or anything it'll geo code it for us it's a store added click OK and now you can see that store is is on our map alright so even though the application is pretty simple in terms of functionality we'll be doing a lot we'll be dealing with Mongoose map box on the front end we'll be using the MapQuest API to do our geocoding will be using postman to basically work with our API until we have a front-end and like I said the front end is gonna be just Fenella JavaScript using the fetch API I'm not going to use react or anything like that even though I do have a react icon up here for some reason how much or why and I just want to mention if he took my nodejs API master class course on udemy a lot of this stuff we're gonna that we're doing in this video we did in that course just to let you know if he took that we'll be creating custom middleware in Mongoose and implementing our geo coder just like we did in that course alright so let's go ahead and get started okay guys we're gonna get started so obviously you need nodejs installed if you don't have that you can go to node.js org and just download either the long-term support or the current version just get that set up and then we need to create a database so I'm using MongoDB Atlas which is a cloud version of MongoDB if you want to download it and install it on your machine and use it locally you can do that as well but basically I just signed up for an account and logged in and I'm gonna go ahead and build a cluster I'm gonna choose the free tier and just keep AWS checked as my provider and then down here I'll just rename the cluster to let's say demo cluster and create ok so that's going to get created it says between 1 and 3 minutes so my cluster is created it took about a minute and a half or so and now if I click on connect we should see these options here and when we're ready to plug in our MongoDB URL we can click connect to application and just grab this connection string okay so that should be all set and then you should be downloading postman if you don't have it or some some way to make HTTP request to our API okay and I have postman up and running as you can see right here okay so let's jump into vs code and I just have an empty folder called store locator API even though we're doing the front-end as well but most of our attention is on the backend so I have my terminal open I'm gonna go ahead and NPM in it - why that's gonna create a package JSON file and I am expecting that you know at least some nodejs if you don't I would suggest stopping this video now I'm going and watching my nodejs crash course okay so we need to have some dependencies we want to install so clear that up and we'll do NPM install Express which is our web framework Mongoose which is our object data mapper so we can create our models and all that and then we also want dot C and V which takes care of our global config variable and we're also gonna install node - geo coder which is going to handle the geocoding and I think that's it is that all we need well we're also going to install cores so that we can we can have cross-domain support alright so we'll go ahead and install those dependencies and then we just have one more which is going to be a dev dependency and that's node mon so let's say npm install - uppercase d node mon and node mon i'm sure most of you guys know what that is it just allows you to constantly watch your server and not have to keep restarting it so in our package jason i'm gonna add a script here called dev so this is what we'll be running to run our application on our local machine here and we're gonna run node mon and then the name of the file which i'm actually going to call server j s and i'll go ahead and change this main value to server j s and then i'm just going to have a regular start script as well for case we deploy this and then that's just gonna run node server j s ok so we'll save that that should take care of our package jason now let's create our server j s so this is basically just our entry point basically we want to bring in all of our dependencies we are going to be using the path module later which is a core node.js module to deal with file paths so we are going to bring that in now and then I'm just going to copy this down a few times we want to bring in Express okay we want to bring in dot env for our global variables and we want to bring in cores and we're just cores is really simple to enable here we just need to add one line of middleware but we also need to load our environment variables so let's say load environment variables and to do that we take our dot env module here and we call our object and we call a config method and since we're going to be putting our config folder inside of a folder called config we need to add an object here with a path describing that ok so the path is going to be slash config and then it's going to be a file called config dot E and V that's where we're going to store all of our global variables ok then we need to just initialize Express so Const app equals Express and then we're gonna set our port now our port I want to set to a global variable so I'm going to go ahead and create that config folder and inside config I'm going to create a file called config dot e and V and we're gonna have a few things in here for now we're gonna have the node environment which is going to be set to development by default and then we want the port and I'm gonna set that to 5000 if you want to use something different that's absolutely fine okay so we have those set now to access this right here this this global variable of port I can simply say process dot E and V dot and then the name of the variable now the reason I'm setting it into this variable is because I want to put in or condition because if that's not found then I still want to run it on 5,000 and if you again if you want to use a different number that's fine and then we just need to call app dot listen and we're gonna listen on the port and then just have an arrow function here and we can just do a console log just so we know that we're connected and in here I'll put some back ticks and I'm going to say server running in and then I want the mode are the not the mode but the development environment the node environment so process dot he and V dot node underscore env and we'll say mode on port and then we'll put the port variable ok so it should say like server running in development mode on port 5,000 so let's save that and let's try to run this with NPM run dev and there we go everything is running fine now there's a couple pieces of middleware that we need to put in here so right below where we initialized app let's add the body parser middleware so that we can actually send data to our API and that's easy we just do app dot use and then we pass an express dot jason because we're gonna be sending json data and then to enable cores we just do app dot use and simply call cores with parentheses alright now as far as our routes go let's just create a sample route here we'll say apt-get and the way we're gonna structure these routes it's going to be slash API slash version one slash and then whatever the resource which in our case is going to be stores we're only going to have one resource in this API so if that's called let's go ahead and put a call back here so request response and we'll just do a console actually yeah a little just to uh exercise we'll do a response so res dot send hello so let's head over to postman you could use your browser for this if you want but I'm gonna use postman I'll make this bigger so I'm gonna make a get request to HTTP localhost port 5000 dpi version 1 stores and send and I get back hello and you can see it's a 200 response so everything went ok now I don't want to have my routes in this file even though technically we only have two routes one is to get stores one is to add a store I still want to make this neat and have a separate routes file and then also have a separate controllers file where we actually have controller methods just to do this kind of the right way so let's create a folder called routes and inside routes we're gonna have a file called stores dot J s and we want to be able to use the Express router here so we're gonna bring in Express and say require Express and we need to create the router so let's say Const router set that to Express dot router like that and then we have to export the router in order for this to work so module dot exports equals router and then when we want to create our routes we'll just go ahead and grab this will cut this put that inside here and just change this app to router so it'll be router dot get all right now we have to link this to our entry point our entry file here our server J s so let's go ahead and just say routes even though we're only gonna have one so we can say app dot use and for the route slash API slash version 1 slash stores we want to require our routes file which is going to be in dot slash routes slash stores okay now back in here since we have the route defined here this API version one stores we don't need it here we just need a slash because we're hitting that exact route okay so if I save that now you can see that we have no errors down here we should get the same response so if I go ahead and send we get hello back alright so we've just moved everything to the routes file now I want to take it a step further and create a controllers folder okay so let's create a folder called controllers and technically you don't have to do this in and an API so small but it's nice to just have it structured neatly in case you're gonna scale it in case you're gonna add more to it so let's add a file and controllers called stores j/s and then in controllers we're gonna have our functions and what I like to do is put kind of a signature here if you took my node course you know this I like to put a description of what this is so this is going to get all stores and then we'll put the actual route which is going to end the method which is going to be a get request to API version one stores and then I'll put the well usually I'll put the access I mean we don't have authentication so it's always gonna be public but we'll go ahead and still put it here so access public now to create a controller method we just need to export it so exports dot and then whatever we want to call it so in this case get stores and then we set this to a function with request response and next I'm gonna use an arrow function you don't have to use an arrow function and then let's just take what we did here which is just res send hello and put that in there for now okay so now we want to bring this get stores into our routes so up here we'll use a little destructuring and we'll pull out get stores and I'll pull that out from our controller so it's gonna be dot slash controllers wait a minute we need to go outside we're in the routes folder so we need to go dot dot slash and then into controllers and then stores ok and then when we want to use this route instead of doing router dot get and all this stuff we can simply say router dot route and we're talking about just the the route route here just slash and then for a get request okay so when I get requests when we when we send to get requests to this route right here which pertains to this then we want to run get stores okay so I'll go ahead and save that and we should get the same result we should still get hello okay so what we want to happen now when we hit this route is we want to fetch stores from our database so there's a few things we need to do one we need to bring in our MongoDB URL so back to Atlas I'm going to so you go to connect and then connect to your application and I'm gonna copy this string right here and let's go back to our config file and we're gonna call this underscore URI and then set that here okay and then you're gonna have to just replace this with your actual password which in my case is just Brad T it's the same as the username and then I'm also going to change the name of the database from test2 I'll change it to store locator or whatever you'd like okay so we'll save that and we need to be able to connect to our database before we can actually fetch anything from it so there's a few ways you can do this I like to create a config file so I'm in the config folder I'm going to create dbj s and in here we're gonna in Mongoose which is what we're going to use to connect so we want to require Mongoose and then I like to create a function called connect dB and I'm gonna make this an asynchronous function because Mongoose returns a returns promises and you can either use the dot then syntax or you can use a sink of weight I think a sink of weight is a little neater so that's what we're going to use here all right so we just want to create a try-catch block and in the Tri we're going to create a variable for our connection and since we're using a sink of weight we just need to call a weight before we call Mongoose dot Connect okay and then Mongoose Connect takes in the string this URI so again to use any of those config variables we just do processed dot E and V dot and then whatever we called it so in this case URI now with Mongoose there's a bunch of options that we have to pass in in order for it not to complain and give us a bunch of warnings so I'm just gonna paste those in so we have this new use new URL parser use create index use find and modify use unified topology some of these you probably probably don't need these actually because we're not doing anything that has to do with that but just in case you get you do an update later or something if you add on to this it's just good to have these options here okay and then after we connect I just want to do a quick console log and I'm gonna put some backticks in here and just say DB connected and then I'm going to put the basically the connection string here so we can take that connection variable and then we can say connect dot host okay so it'll just let us know that it's connected to that host and then if something goes wrong I'm just gonna first console error whatever the problem is and then I'm gonna exit out of the app with process dot exit and we want it to exit with failure so we want to pass in a 1 ok and then the last thing we need to do is just module dot exports our function which is connect dB all right now we have to bring this into our server J s so let's head over to server J s and bring in that function so we'll say Const Connect DB and we want to bring that in from our config file our database config so / DB and then we just need to call it so I'm gonna call it right here I'll just put a comment it's pretty self-explanatory but we'll still put a comment so connect DB all right and now down here right after it says we're running in development mode it says MongoDB connected and it gives me my host ok so now that we're connected we need to create a model for our store so let's create a new folder called models and inside models we're going to create a new file called store with a capital assets just convention store j s singular and we need to create a schema so let's say Const Mongoose we need to bring in Mongoose and let's create a schema so we'll call this store schema and we set this to new Mongoose dot schema and then this takes in an object of field so we're gonna have a store ID and we're gonna set this to have a type of string and it's going to be required so for required we could just say true but we can also make it so that it says a message if it if it's not required and we do that with brackets and then just add in a second value here of whatever the message please add please please ask please add a store ID all right and we'll say that we want this to be unique so that there can't be two of the same store IDs we'll go ahead and just set trim to true trim any white space and let's set a max length of we'll do a max length of ten I guess and we'll say store ID must be less than ten characters all right so that's the store ID now the location field is going to be our geo jason-- jason-- object all right so if we go I close the tab but if we just search for Mongoose geo jason it gives us the format of this so right here I'm just gonna copy this this whole location field right here and I'll just paste that in here all right so we have a type value so type string and then enum just means that the only values that are going to be allowed is what's in here and that's a point this is gonna be a geo jason point okay we don't need these comments here and then it's required true I'm actually going to get rid of that because we could run into some issues with that and then coordinates so we have type number I'm also going to get rid of required two here and I'm going to give it an index of a 2d sphere all right and then we can add other fields as well so in this location we can have additional fields such as I'm going to do formatted address and you could do so say formatted address which is going to be a string but you could also do like zip code or whatever you'd like to do because the geo coder that we're using once we send out the address that we send to the API we can get back anything we want from that address we'll get the the latitude and longitude we can get the formatted address which will go here we can get the zip code the state the country all that stuff so if you wanted to put more in here you could but I think the formatted address is fine and then the last thing I want to put under location is just a created at which I usually do all the time which will just be the current date and time so the type of field will be date and the defaults we're going to set a default value which will be date dot now which will put the current date and time okay so we need to export this so we'll say module dot exports and we need to export this as a model so we're gonna say Mongoose dot model and this model is gonna be called store and then we pass in the store schema all right so that's the basics of creating a model in Mongoose now one thing I forgot to do is actually add the address as a field so we're gonna say address and give this a type of string and this is gonna be required and I'll explain why I'm doing this in a second so this is gonna be required true please and an address okay so what we enter ultimately in the in the form in the front end for the address is gonna is going to pertain to this but we're going to create a piece of middleware that's going to convert that address into this location with coordinates and all that stuff that way we don't actually have to enter the the latitude and longitude and stuff into the API we just add the address and then the geo coder will turn it into this location and then ultimately I'm going to make it so that this doesn't even get saved in the database only this does okay if that makes sense because when we send data to our API it only allows us to send the fields that are in this model like if I send a name it's not going to work it's not going to go through because I don't have a name field in my model so let's go back to our controller and in our controller here we want to bring in our model so let's go up above and let's say Const call this store and set that to require our model file which is dot dot slash we want to go up one level into models and then into store okay and then down here Mongoose like I said returns a prot the connect method returns a promise so does everything else if we use find or create or whatever it all returns promises and I like to use a sink await so I'm going to make this function asynchronous okay and I'll just get rid of this and let's do a try-catch so inside this try let's go ahead and well basically this what this is going to do is get stores from the database which we don't have any at the moment but we can still do this and it'll just it'll just give us an empty array so let's say Const stores and we can set this to a wait okay because this is going to return a promise we can use the store model that we just brought in which has a method called find which just gets everything in that collection so this will fetch all the stores now as a response we're gonna go ahead and return res Dot status of 200 and we're going to tack on some jason-2 that okay so in this JSON method we want to pass in an object and the way I like to structure my API responses is to set a success value which in this case would be true we can also set a count value and count the stores so that variable we can just count lame we can just call length because it's an array and then of course the data which is going to be the stores alright so that's a successful response now down here if something goes wrong well it's just first of all console error whatever happened and then we'll go ahead and just res dot status and send a 500 error which just means a server error and I'll tack on some jason-2 that it'll just say error and then a string of server error all right so let's save that and now if we go to postman and again we hit this API so API version 1 slash stores we get success true count zero data is an empty array now success is true even though we have no data it's still a successful response is just nothing in the database nothing went wrong there's just nothing there okay so now what I want to do is create the ability to add a store so let's go back to our controller here and I'm just gonna show copy this whole thing right here so we're gonna have another route and this is gonna be to create a store and it's gonna be a post request oops not poor post to the same URL but a different method public and then here let's change this to add store as a method okay and then add store we're going to get rid of this everything in the try and let's say Const store actually you know what first of all first what I'll do is just console.log the request dot body cuz that'll show us what actually comes in when we send data so let's save this now this add store is just it's not plugged into our routes yet so we want to go to our routes and bring in add store and then down here on this router dot row we can tack on dot post because it's the same route it's just a different URL and we have a different function to run which is add store so I'll save that now if we go back here and I just open up another tab and make this a post request to the same URL we'll still going to slash stores and then since we're sending data we need to add a headers value so under headers let's add a content type and the content type is application slash Jason that's the type of data we're sending so in the body we want to send some raw jason so put some curly braces here and we need a store ID since it's jason we need double quotes around the key and the value pair so we'll do 0 0 0 1 and let's send address and we'll send ten Mainstreet payroll mass okay so if I send this it's gonna hang right now see how it's just it's not giving us anything back but if I go down to the console you can see what was logged it's just an object with store ID and address because this is what it's doing it's just logging we didn't send a response back yet so I'm just gonna cancel this and now let's finish this up I just wanted to show you that request stop body gives us the object that we send in the body okay so we'll get rid of that and now let's go ahead and just create a variable called store and we're gonna use the create method that Mongoose gives us with our model which returns a promise so we have to use a weight so store dot create and then we just want to pass in our request dot body which is what I just showed you this right here now we want to send back a response this will save it to the database we want to send back response so let's say return res dot status we'll send a 200 which means everything's ok and then in the JSON data we're gonna send again success true and then we're gonna send for the data this that's just the one store that we just added ok which is coming from this variable so this will create it in the database as well as return it to this variable and then we're sending it as a response and then in the error we're just we're doing the same thing we did above now remember how we have in our model we have the store ID is unique so that'll give us a specific error if that happens actually I'll go ahead and just I'll show you that after because we are console logging the error but let's just save this and see what happens so we'll go back here and we'll send this same thing again and check out what we get back success true and then it gives us what was inserted into the database that one store it has an eye d that gets created automatically with MongoDB we have a store ID that we added an address and a created at okay now watch what happens if I try to send this again with the same store ID so we get back just server error I want this to be more explanatory though and tell us that you know we already have this store ID so if we look at the console log here because we're console logging this error it gives us some stuff here it gives us a name error a code and then this message here so what I'm gonna do is narrow it down by this code and then send a special response if this code is there meaning that it's a duplicate field so let's see we'll go let's go right under here and just put an if statement and usually like in my node course and my API master class course we create a custom error handler that handles all this so that we don't have to do it in every single route but this is just kind of a quick way to show you how to do this so let's say our dot code if that is equal to what is it 11,000 then let's return a res dot status now this isn't a 400 I mean this isn't a 500 it's a 400 because it's a user error they tried sending something that shouldn't have been sent which is a duplicate field so it's a 400 instead of a 500 and then for the Jason we'll go ahead and just send an error message and we'll say this store already exists all right and then if it's not this code and it's still an error it'll just send server error so if I save this and I go back and I try to send again now we get this store already exists okay now the issue we have at the moment is in our database and we can actually look in our database atlas so if we go here we go to collections that shows us what we have in our database and all we have is address 10 Main Street Averill mass and that's not what we want we want a Geo JSON object so what I'm gonna do here is implement a geo coder and remember we installed something called node geo coder and this supports a bunch of different libraries including Google Maps I think MapQuest is the easiest to use so that's what we're gonna use but basically it'll give us like all this stuff latitude longitude country zip code we can get all this information just from that one line that one address that we sent so we're gonna create something called Mongoose middleware to do that all right but first first I want to create a little utility that will implement this geo coder so like I said we're using MapQuest so we're gonna just search for MapQuest API and you just want to log in which if you click sign up let's see I'm gonna click login and let me see if I remember this okay so once you sign up and you log in you'll be able to create a key actually I think they create one automatically you have my dev camper here I have this one my application that should work if I click on that yeah this one right here is valid so just you know create a new key and then you want to grab this here the consumer key not the secret the key and then we'll put this in our global variables inside of our config dot E and V so in here let's go ahead and I'm gonna say geo coder and I'm also I'm gonna put the provider just because this can be different there's there's like a hundred different providers you can use we're using MapQuest and then let's say geo coder underscore API underscore key please use your own not mine and we'll save that and then what I'm going to do is create a folder called utils and inside here we're gonna create a file called geo coder dot je s so we want to bring in our geo coder so we're gonna say node geo coder actually I think if we look at the github page for this node geo coder github it has like the exact to set yeah so you can see they're bringing it in and then we set some options including the provider and then we initialize it and we just need to export it so yeah I'm just gonna copy this yeah and then paste that in and I'm not gonna use var so four options for provider this is where we can put our global variable for our geo coder provider which is MapQuest so we can use process dot E and V dot geo coder underscore provider and then let's see you get rid of the comments HTTP that's good for matter no we'll keep that now this here is where our key goes and our key is in our config file so process dot E and V dot geo coder underscore API key okay then we we initialize it here and then we don't need this we just need to export it because we're gonna be using this in our Mongoose middleware so let's say Hmong module exports equals geo coder okay so this utility now we can bring into our model so I'm going to close this up and go into our store jsr model and in here we want to bring in our geo coder so const geo code R equals require dot dot slash utils slash geo coder all right now to create a piece of Mongoose middleware we simply take the schema let's put a comment here we'll say geo code and create location so we take our schema store schema and we can either call this after before save or after save or pre or post save we want pre because we want this to run before it she gets saved in the database because we're actually changing what's going into the database instead of the pr address which is happening now we want to geocode it and save basically save the coordinates and stuff like that so we're gonna say pre save and then we're gonna run a function let's say async function and then every piece of middleware gets passed in next okay you always have to call next which will call the next piece of middleware and then let's create a variable here called Lok okay because what I want to do is get the geo coded location from the address so we're gonna wait because this geo coder will return a promise so geo coder and then there's a method called geo code and then to access the address this right here that's passed in when we send the data we simply just need to say this dot address all right now what I'll do is just a console log of Lok and show you what that contains so this should automatically run when I try to save a new store but I'm actually going to delete the one I already saved so in Atlas I can go ahead and delete this so that there's nothing in the database okay so that got deleted so I'll go back to postman if I try to search for stores you can see there's nothing there so I'm gonna re add this one so send okay so it got saved but let's go back to our console here and see what this gave us on save we have the latitude longitude city state code zip code street name country code provider so it gives us all this stuff just from this little line right here okay all those fields that we can save in our database now we need to format it as a point for our location field right so let's ahead and get rid of that and let's say this dot location meaning this field right here we want to save we want to add in to that we want it to be an object with a type okay because remember up here we have a type and it has to be point okay this is enumerated this this just means that it has to be point so we want to set that to point right and then we want to set a coordinates value here and this is going to be our longitude and then latitude and if we look down here and loke we have this longitude and latitude now this is actually an array you can see the bracket right here even though there's only one object it is an array so we have to say lok and then the first item in the array which is 0 and then longitude ok and then we want lok first item in the array first and only and then latitude so that's our coordinates and then anything else we wanted to add I will actually we only have a formatted address but we could add zip code and all that here as well but since we have formatted address let's add that so that is gonna be lok first element in the array dot formatted address and you can see that right here so this will go in our database even though we're not using it in our front-end it'll still be in our database ok now the last thing that we want this two more things you want to do one is we don't want to save the address in the database the actual address field that's typed in so let's say do not save address and the way we do that is simply take this dot address and set that to undefined and then it won't get saved into the database and then the last thing is just call next ok since this is a piece of middleware we have to call next ok so let's save this and I'm gonna once again just delete what's already in the database which is the one with the ad yes okay because it's been just putting these two straight address in let's delete that okay and then we'll go back to postman we'll send the same exact request again with this address and see what we get back so now we get back in our data we get back this location field type point we get our coordinates and we have a formatted address okay and notice there's no just there's no regular address field because we set that to undefined before it actually got saved into the database so this is exactly what we want okay and then I'll add another one here let's do ten Main Street Lawrence mass so I'm just doing cities around just ten Main Street for cities around that area oops we need to change the ID because that's two already exists and there we go so now we have two entries in our database so really that's it for our back-end now in order for us to access the front-end we're going to create a static folder in our in our node structure so let's see we're gonna go over here let's close all these up and let's create a folder called public and then we just need to let no js' know that that's our static folder so basically we want to be able to put HTML files in their CSS front-end JavaScript all that stuff so in server j/s we're gonna set our static folder so the way we do this is with app dot use and in here we want to say Express dot static and pass in our path join and we want to join let's say underscored our name just means the current directory and then public so we're just defining that as our static folder and now in public let's create a file called index dot HTML and let's just add a boilerplate here and say store locator and for now let's just put an h1 and say I'll just say hello alright so if I save this and I'm just gonna restart our server here and go back to the browser and let's go to HTTP localhost port 5000 and we get hello alright so since that HTML folder is in our public folder which is our static folder we can just go to whatever dot HTML so if we create actually we are gonna create another HTML file called add dot HTML and if I just go ahead and say store locator add store and I'll put an h1 in here and say add store we should be able to go to slash a dot HTML there we go ok and our API back in the EPI is still running if I go to postman and I make a get request to API version one stores you can see we have two stores with the coordinates with the geo jason okay so now we want to just continue on our front-end so we can close up MapQuest Mongoose we don't need that what I am gonna do is grab bootstrap so I'm gonna go to I'll just say let's just say bootstrap CDN just so it doesn't look absolutely horrible and we'll just grab this okay and let's put this in both index and add HTML so I'll paste that there and we'll paste that here and I also want font awesome for the home page so I'm just going to search for font awesome five CDN and we'll grab it from here CloudFlare just say copy link tag and throw that in right here okay I'm gonna close up at HTML for now because we're gonna do the map page first now we do need map box so let's head over to Matt box forget the URL oh it's just matte box com alright so you're gonna want to create an account it's free so sign in here hopefully that's right yeah okay so I'm logged in and if we click you'll see right here you can choose for iOS Android we want web so we'll click that and I'm going to use the CDN you can also use NPM but I'm just going to grab the CDN which is these two files here which we need to grab and put into our index so I'll paste those in the head and now we should be good to use map box all right so I just want to give you like a basic example of map box if I click Next you can see you have to just initialize your map with your token and this will go in the JavaScript so I actually you know what let's let's add the HTML first so in our index.html let's see we're gonna go down into the body and let's get rid of this we're gonna just have a class of container I'm going to use some bootstrap classes we're gonna do my three which is margin on the top and bottom and in here let's put an h1 with the class of display - 4 and let's do text - Center and we'll just say store locator and under that h1 actually in that h1 let's put the icon so I'm gonna have an eye class and this is gonna be FAS this is font awesome FAS and then FA - map - marked and we're also gonna add in here margin right 4 to push the text over a little ok so that should just be an ayat I tagged with this class ok so if we save that and take a look should look like that okay now under the h1 we're gonna have a button to go to the ad store page so let's put in an a tag here with the class of BTN and let's do BTN - success and margin bottom four and this is going to go to add HTML and say add store ok and then underneath that we're gonna have our map container so this is gonna be a div with the ID of map and then we need to have a width and a height here so we're just gonna put some inline style here it's what it's says to do in the documentation so we'll say width of 100 percent of its container and let's do a height for height I'll do 500 pixels and I'm also just gonna add a border radius of 5 pixels okay so that's our map container and then of course we want to link in our JavaScript front-end JavaScript which we haven't created yet but I'll go ahead and do that so let's say script source and I'm gonna call it map dot J s this file okay so inside public we want to create a folder called J s actually this should be J s slash map J s and inside there we're going to create a map dot JS file okay so let's just make sure that this shows up the map isn't going to show but the button and stuff should you can see that takes us to that page we do have the map container here but we have none of the JavaScript to generate the map yet so let's do that let's go into map J s which is a front-end JavaScript file and we need like our token and all that stuff which is right here I'm just going to grab this okay we already have our container we don't need script tags because this is a separate file so I'll paste that in let's change this to Const and then this just initializes a new map box map and then there's different styles you can have as well we're just going to use the default streets version 11 let's see container map I'm going to set a zoom level so I'm going to set the zoom to 9 and then I'm gonna set my Center so this is a latitude longitude Center which I'm going to set the gets Haverhill Massachusetts which is a city near me so let's say 70 1.15 7 8 9 5 and then 42.7 zero seven seven four one and of course you can change this to whatever you want now just having this should show the map so if we go back and reload there we go so it should show the map now as far as plotting points let's go back to the docs here and I'm just going to go to documentation and this right here map box glj s and two examples and then I believe it's ad generated icon see no that's similar all right here add icon to the map so basically I mean you can use custom images if you want they're doing that here with map dot load image we're not going to do that but what we do need to do is add a layer so we need to do all this basically it takes in an ID of points ok we're using geo Jason points that's what our API is made up of and then we have in our data we have an array called features and that's where we have the coordinates of each point so what I'm going to do first is just hard code a point and then we'll go ahead and make fetch request and bring in our data so I'm gonna grab let's see yeah let's just grab all this and in I have them the code the repository in the description if you jot if you guys are following along and you want to copy from that you can but let's create a function here called load map and I'm gonna paste this stuff in okay so I'm not gonna load an image let's see where does this actually end so that has a callback actually maybe I shouldn't have done this because all I want is the add layer which ends right here so let's grab that map dot add layer and I'm just gonna copy that and that's gonna go in place of load image because we don't need to load a custom image so right here we'll paste that in okay so we have map dot onload and then a function and then map dot add layer alright and then let's see for our point coordinates obviously we don't want 0 0 I'm just gonna grab the center coordinate we have which is Haverhill mass and I'm just gonna paste that in as this coordinate so basically you would for all your different locations on your map you would just have an array of these objects but we're only gonna have one for now so it has a type of feature and then a geometry object the type is a point so it's a geo jason point and then we have the coordinates now we can also add a properties to this properties the properties object and we can have like a store ID or a title or whatever you want to have let's just we're just gonna have the store ID as kind of the title because it's basically all the same store that's the idea and then we can have an icon and we'll use the shop icon you can look in the docs for the for the options for that and then for layouts we're not going to put out an actual image like they did we're gonna use a sprite so we want we want some curly braces and then I - 15 for the sprite and you can look those up as well if you want for the icon size I'm gonna make it 1.5 and then I'm gonna add some other stuff as well so I want a text field because in addition to just the icon I want I want it to have the store ID so we're gonna say text field and set that to inside quotes and curly braces store ID okay which is going to pertain to this property any properties you put up here you can use down here and then I'm gonna just change the text font so we can actually put in some brackets here and I'm gonna use open sans semi bold and Arial Unicode m/s bold so you can set different fonts and then I'm gonna set an offset for the text or else that's gonna be like on top of the icon so we're going to set that to actually this is going to go into here and it's the X and y-axis we want to do 0.9 on the y axis and then I just want a text anchor this will help position it text anchor is gonna be top okay so this should give us one point because we have one item in our array it's static later on well we'll get it from the API so we just need to call our function what I call it load map because it's all in a function so we're gonna call load map okay so let's see what that does we'll go back to our app and reload and there it is zero zero zero one okay so we just manually plotted a point on this map so what we want to do now is actually fetch it from from our API okay because we have these locations here in our database in our API so we want to plot those instead of just some static coordinates so what I'll do is create another function let's put a comment here let's say fetch stores from API and then this is going to load map with points or with stores okay and the way that I'm gonna do this now is instead of hard-coding an array this features right here see this array where these brackets are I'm going to let's comment that out just so we can see the structure of it and for features instead of having a hard-coded array let's pass in a variable called stores whoops what get stores stores because what we're gonna do is pass in stores to load math all right so back up here let's create a function called get stores and what we want to do here is use the fetch API to do just that get our store so I'm gonna use a sink await so it's a sinc function and we'll say Const res equals a weight and we want to fetch from our API we're on the same domain because we're in the public the static folder so we can just do fetch slash API slash version 1 slash stores all right we need to convert it to Jason so we get the data by weight rezzed jason that will give us the json data okay and then let's actually just do a console log here of the data and then instead of calling load map here I'm gonna call get stores right now load map isn't even going to get called so let's just check that out we'll open up the console here the front-end console cannot use import statement outside of mod oh it did this to me before I don't know I just popped this in here for some reason let's get rid of that okay so check out what we get success true count two data and then we have our data which is a location field an underscore ID a store ID and it created at and the location has the coordinates so that's what the data from the database looks like now we need to convert this or map this we're going to use the map method to turn it into this okay so we need to change the the structure of the object so the best way to do that is with the map method so let's create let's see let's create a variable called stores and we'll set that now this data has an object called data in it so that's what this data dot data is and then we're gonna call dot map which is a high order array method to loop through so we'll say for each store and then we're gonna call a function and we want to return a new array a new structured array with new structured objects which are going to have a type feature actually I can just I can just copy this so this object here just grab that and just get rid of the just uncomment so we're going to return that and then geometry point and then the coordinates are going to be dynamic right we need the we need the latitude and longitude now if we look at the return data you can see we have coordinates which is an array with 0 1 ok so the way that we can access both of these is simply by doing let's say store so the current iteration or the current store location dot coordinates and we want the zero index that will give us the latitude and then we want the current store location dots coordinates one okay so that will give us the dynamic coordinates and then for properties this should also be dynamic the store ID so we'll take the current store and just get the store ID all right so what we've done is we've taken the data from the database and reconstructed each object in to look like this which is what map box needs and then what we'll do is just call under here we'll call load map and we'll pass in stores which is that that converted array and then that will load this and it'll pass in stores as the features and we can get rid of this okay I hope that makes sense so this is a little hard to explain so let's save that and then let's see if that works so if I go back and I reload now you can see one in two so these are both stores that are in our database so it's working ok so the last thing we want to do is want to be able to add a new store so let's do that let's go first of all to our add HTML and let's finish up this page let's see so this page isn't too bad it's just gonna be a form we're gonna get rid of this h1 in the body and put in a context I'll just copy what we have in the index even the script although we're gonna use it we're gonna create a new JavaScript file for this so it's going to be called add j/s and then up here let's change this we'll get rid of the icon in the heading and we'll just say add store and let's see we don't need this we definitely don't need the map we just want to form so let's create a form we're gonna give this form an ID of store - form and let's give it a class of mb - for okay we don't need an action because we're going to use this javascript and inside here we're gonna have a class of form group and let's have a label we'll say for store ID - ID store ID and then we need an input and this input will have an ID of store ID and a class of form control alright so that should be good and then I'm just gonna copy this form group because now we need a store address I'll change this let's just actually yeah we'll change this and this to store - address okay and then we just need a submit' so let's do a button with the type of submit and let's add a class BTN BTN - primary and then let's also have a back button which is gonna be a link so we'll give this a tag a class of BTN BTN oops dot b TN - secondary and this is gonna go to index dot HTML okay we'll just say back so let's save that see what it looks like so if we go to add store good now for the functionality remember we have an ID on the form so we can add an event listener to listen for a submit and then we have an idea on the inputs so we can get that data store address store ID so let's create a new file in the public j/s called add jas and there's a million ways you could do this and of course you could use react or angular or whatever you like I'm just trying to do it in a very simple way here so store form set this to document dot get element by D store - form and then we also want the ID field which is an ID of store ID change this and then this is store address ok so we have our donuts everything we want from the Dom and then we're gonna have an event listener on the form so let's say store form dots add event listener and in in here we're gonna listen for submit and then we're gonna call a function called add store ok so we'll create that function say send posts to API to add store alright so first thing we want to do we actually want to pass in our event parameter so that we can prevent the default behavior so if we call prevent default that'll stop the actual forum from submitting okay and then I just want to make sure that they enter data in the forum so we'll say store ID dot value if that's equal to nothing or store address dot value is equal to nothing then let's just send an alert and it's kind of a cheap way to do it but that's fine we'll just say please fill in fields okay then what we want to do is get our data so let's call this send body this is all going to send in the body to our API and that's gonna be the store ID which is going to be the store ID dot value okay so the value of the input text and then the address will be the store ID I'm sorry store address dot value okay so that's what we want to send to our API now we want to do our fetch so we want to use a try-catch here and let's do we'll create a variable called res for response we want to a weight fetch and speaking of that we have to make this asynchronous since we're using a sink of weight here all right so we're going to weight fetch and we want to make our request to which we can use quotes slash API slash version 1 slash stores but in this case we're making a post request so we'll add a second object here second parameter of an object and set the method to post and we also want to set headers we want to set the content type so content-type is gonna be application Jason just like when we used postman okay and then under the headers we want our body now the body we're sending that send body object but we're gonna wrap it in Jason dot stringify and then send body okay now as far as let's see yeah so after the res here as far as the error handling goes we want to check to see what the response is here if it's a 400 because remember we're sending a 400 if the store is already there so we'll say if res dot status because it'll give us a status back if that is 400 then we know the store ID exists so what we'll do is we'll throw an error here let's say oops we wanted to say throw error and we'll just say store already exists okay and then underneath that so basically what this will do is it'll throw it so we can catch it here and then I'm just gonna alert it so we'll alert actually yeah we'll just alert the error because this should be whatever we pass in here this I like Axios better I don't usually use the fetch API usually use Axios because I like the way that error handling is better but I didn't want to use any extra libraries alright so throw the aera so if everything goes okay then let's just alert and we'll say that the store has been added or store added and then let's just redirect so with vanilla JavaScript we can use the window object and we can say location dot href and we can set this to whatever we want in this case we're gonna go slash and start HTML okay so go back to the map and down here in the catch let's just return after this all right so I think that should work looks right to me I don't know let's try it so ad store and let's say zero zero zero let's try one we already did which is 0-2 and we'll say 10 Main Street aims very mass Submit okay so store already exists so it doesn't let us do it let's change it to 3 and submit store added ok redirects us and there it is 0 0 0 3 all right so our application is complete we've built a back-end a back-end API with Express Mongoose no geo coder with MapQuest we created some Mongoose middleware so that we could create geo Jason fields and then we built a front end that could consume our API using matte box to display our geo Jason fields here after fetching them using the fetch API ok so quite a bit of stuff that we did in this little project hopefully you enjoyed it and hopefully you learned a little something even if you didn't understand the whole thing hopefully you learned something that you could use you know in your future development so that's it thanks for watching and I'll see you next time
Info
Channel: Traversy Media
Views: 86,203
Rating: undefined out of 5
Keywords: node.js, mongodb, node mongo, express, mapbox, geojson
Id: 9FQrFah9rnc
Channel Id: undefined
Length: 76min 42sec (4602 seconds)
Published: Tue Dec 31 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.