Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialKrystal Jackson
8,598 PointsCan I do more than redirecting with Nodejs and Express?
So far all I've learned is how clicking buttons in forms take me from one page to another but I have buttons on the page that I want to trigger interactions on the page such as returning results on the same page.
Say for instance. User is on the search page. User types in a person who's bio they are looking for. They click the 'search' button. I want to search the mongo database, find the person and return the their bio on the very same search page. With regular JS and Jquery I can do this with no problem. In node.js and express all I know how to do is make buttons take me from one page to another but this doesn't help me because i want to remain on the same page.
Keep in my mind, I am hoping to not have to use another programming language like angular, etc to accomplish this.
2 Answers
Dane Parchment
Treehouse Moderator 11,077 PointsExpanding upon Kenney's answer, it is possible to accomplish what you want to do through the use of routes in express.
In basic terms a route basically determines how a server/application responds to a client's request. Using express we can easily setup a few routes that accomplish the task that you want to do, in fact I will walk you through a simple application right now.
NOTE
- The application is written in vanilla JS (I didn't even use JQUERY for the AJAX requests, though of course, if you know JQUERY then writing these requests should be pretty self explanatory.
- The application will not be using MONGODB, or any type of database, I am going to assume that you will be able to figure out how to utilize the information learned to implement that. Instead I will be using a simple array that is converted to a string. In real-world application you will tend to receive a JSON request instead that must be parsed!
- This application is NOT well written, nor is it a representation of how this is done in real applications, my goal is simply to show you how this is done with express in the most basic way possible. (Basically, I wouldn't copy-pasta this code into a production environment)
- Lastly, the application is actually written as two separate applications: The front-end, and the back-end. The front-end will have the site that the user is going to visit, and will be the one sending the request, the back-end will house the server, and when the server is running it will receive requests from the client, and send data back, post data to the database, etc. (This is how most real-world applications are written: with separate front and back ends. YOUT DO NOT HAVE TO DO IT LIKE THIS, YOU CAN HAVE THE ENTIRE APPLICATION ON THE SAME DIRECTORY, OR YOU CAN EVEN CREATE A HOME ROUTE THAT RETURNS AN ENTIRE FRONT-END ( OUT OF THE SCOPE OF THIS HOWEVER)
Well then, let's dive straight in shall we?!
Setting up the server
Since you talk about having node js, I am going to assume that you already have it installed! So, open up your terminal and let's create a new project directory for our server to stay in! So let's use mkdir to create a new directory, I will name it: routing-test-backend
mkdir routing-test-backend
Once in the directory we need to setup up our package.json and then install express through npm, so lets go ahead and do that right now, in your terminal do the following:
npm init -y && npm i express -S
This will create a new package.json with all of the default settings and then install expressJS to our dependencies (since it is required to run this application).
Next we will create a new file and call it server.js (you can call it whatever you like), so in your terminal:
touch server.js
With this file created let's review what our directory structure should look like for the back-end part of the project!
routing-test-backend
|---------------------- package.json
|---------------------- server.js
Now for the meat and potatoes, let's write our server, so open up your favorite text editor/IDE, and let's get coding! Open up your server.js and write the following:
const express = require("express");
const app = express();
const USERS = [
"User 1",
"User 2",
"User 3",
"User 4",
"User 5"
]
function usersToString() {
var list = "<ul>";
USERS.forEach(function(user) {
list += "<li>" + user + "</li>";
});
list += "</ul>";
return list;
}
//Server Port and Listening
app.listen(3000, function() {
console.log("Listening on port 3000...");
});
//Route for users
app.get('/users', function(req, res) {
res.status = 200;
res.send(usersToString());
});
Let's break this down, first we require the express library, and then instantiate it. Next, I created an array of users (this is our stand-in for the database), Then I create function that simply turns that user array into a string that represents a <ul> tag with each <li> within it representing a user.
Finally we move onto creating the port that the server will listen to, this is important, because we know that by default express will default to localhost as the hostname for the server, but because it is listening to a port, any request must be sent to: http://localhost:3000.
Last but not least, we move onto our route! This is where it gets interesting so let break it down for you even further! A basic route has the following structure:
app.METHOD(PATH, HANDLER)
Since we are looking to retrieve data from the server, the METHOD we use is get in order to listen for a get request!
app.get(PATH, HANDLER);
The PATH is just that, the path on the server that we are making the request to (it can be a file that is hosted on the server, or a route) in our case we set the PATH to be "/users" which means that the server will be looking for the request at: ------> http://localhost:3000/users.
app.get("/users", HANDLER);
Next we have to deal with that HANDLER. Basically the handler is a callback function that accepts to parameters: req, res. They are both hard-coded for the handler and represent the request and the response (I think don't quote me on that, my vanilla express is kinda rusty). So we state that we want the response status to be 200 (A standard code for OK, though honestly you can omit that, as by default I believe Express sends it as a 200, but it does demonstrate how you can change the status if you want to for example send an error code if the userlist is empty). Next we specify that we want to send back to the client the data that is represented as an html string from a function we created earlier!
app.get('/users', function(req, res) {
res.status = 200;
res.send(usersToString());
});
And that is it, our server is created, let's run it by going back to our terminal and typing:
node server.js <----- note that you must be in the routing-test-backend directory for this to work
If you see the text: "Listening to port 3000....." then you know that the server is running properly!
(OPTIONAL)The front-end (I say optional because if you have knowledge of AJAX already, then this should be pretty self explanatory)
Let's start by creating a new directory called: routing-test-frontend then creating some default files for it:
mkdir routing-test-backend && touch index.html && touch app.js
we should have a directory that looks a lot like this:
routing-test-frontend
|---------------------- index.html
|---------------------- app.js
Now let's just create some default code for our html, I shouldn't have to explain it:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Routing Test</title>
</head>
<body>
<h1>Users</h1>
<p>Click the button below to show a list of users on the "database"</p>
<div id="user-list"></div>
<button id="requester" onclick="getUsers()">Click Me</button>
<script src="app.js"></script>
</body>
</html>
Now open up your app.js and let's code our AJAX xhttp request!
function getUsers() {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "http://localhost:3000/users", true);
xhttp.send();
xhttp.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
document.getElementById("user-list").innerHTML = this.responseText;
}
}
}
All right, so we create a function called getUsers() that will be used by the onclick event on the button we created earlier. This function starts be creating a new XMTLHttpRequest object. We then open that request so that we can prepare it with some attributes that it needs, namely the type of request (GET), the url that we are sending the request to (http://localhost:3000/users), and if it is asnychronous our not (True for asyncronous false to be syncronous). Then we send the request to the server. Finally we listen for when the state of the request changes, and respond by checking if the responce we sent was accepted and if it OK, if so we populate the user-list element with the data the server sent back to us! In this case an unordered list of users!
And that is it we are done!
Not that the client is accessing a server from a different domain. So you may get errors, that look like this and nothing will happen when you click the button:
XMLHttpRequest cannot load http://localhost:3000/users. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access
This is because CORS (Cross-Origin XHttpRequests) are not enabled on our server by default, so outside urls cannot access it, so let's fix that, add this to your server.js in the routing-test-backend:
//ENABLE CORS
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
Rerunning the server will now cause the app to work as intended and when you click the button a list of users will show up, without you having to click refresh or leave the page!
If you have any questions please do not hesitate to ask, I know that this is a long answer, and it is possible that I may have misinterpreted your question wrongly!
Charles Kenney
15,604 PointsKrystal Jackson,
This functionality will not come from the backend. I would recommend taking the AJAX Basics course. This will teach you the basics on exchanging data with a server, and updating parts of a web page – without reloading the entire page. You can accomplish a great deal with the Jquery ajax method alone, without learning a whole new frontend framework. That being said, its much easier to work with a framework when your projects become more complex.
Hope this helps
-Charles
Dane Parchment
Treehouse Moderator 11,077 PointsI am sorry, but this is most definitely a back-end task, all the front-end should be doing is sending data to the back-end, and then expecting a response.
EDIT: Ignore what I said, I think I misread your post completely!
Charles Kenney
15,604 Points"In node.js and express all I know how to do is make buttons take me from one page to another but this doesn't help me because i want to remain on the same page."
Maybe you misunderstood me/Krystal. Krystal is asking how she can retrieve data from here mongo database and spit data back on the same page. Obviously the backend would serve this data via an HTTP response, but fetching that data from the backend via the webpage without refreshing requires sending an AJAX request.
Dane Parchment
Treehouse Moderator 11,077 PointsYeah, I edited, my post above, I definitely misread you....I am in the process of hacking out a simple express route, to show her how to go about doing this with Node, Express, and AJAX requests.
Charles Kenney
15,604 PointsAll is well. (: