Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Node.js Tutorial for Beginners (Part 3): Transferring Data Between Pages

DZone's Guide to

Node.js Tutorial for Beginners (Part 3): Transferring Data Between Pages

We continue building our Node.js application, setting up a middleware to help us transfer data between pages and inserting JS logic into our markup files.

· Web Dev Zone ·
Free Resource

Jumpstart your Angular applications with Indigo.Design, a unified platform for visual design, UX prototyping, code generation, and app development.

In the previous article in this Node.js for beginners series, we went over the three popular templating engines for working with Node/Express-based applications: Pug, Mustache, and EJS. After choosing EJS, we set about creating the basic HTML make-up of the application. It wasn't anything super fancy, but we created two web pages that rendered basic HTML. In this post, we'll examine how to connect these two EJS pages and transfer data between them.

Project Recap

I'll be basing the app I work on in this series of a project from a Udemy course (found here) that I've been using on-and-off for a while. I love to travel, and the US National Parks are some of my favorite places to go. To teach myself Node.js, Express.js, templating engines, and Bootrap, I'm going to design an application to keep track of my park travels. In this edition of the series, we'll learn how to transfer data between to EJS pages, allowing us to add our park pictures and names to our app. 

Connecting Our EJS Pages

This actually turned out to be the easiest aspect of the process. I went into it thinking I'd have to use some crazy backend JavaScript in my index.js file. Nope! All I had to do was wrap the button element I'd created in my landing.ejs file last time in an anchor tag, and then provide that path to my parks.ejs file as the link. The code looks this:

<h2>National Park App Page </h2>
    <h3>Parks I've Seen:</h3>
        <p>Park Name: <input type="text" placeholder = "Yosemite, Yellowstone..."></p>
        <p>Park Picture: <input type="text" placeholder="URL"></p>
<a href="/parks"><button>Add to my Memories</button></a>

Now, if we click the button, we go from our landing.ejs page to our parks.ejs page. Easy peasy! I'll come back to this HTML in the next section of this post, so we're not done yet.

Getting Actual Data to Transfer

Finishing the Landing Page

To be honest, this part gave me fits. Going into it, I thought once I had the pages connect, the rest would be a breeze. Oh, how wrong I was.

First off, we need to dive back into that HTML. The HTML for this portion proved exceedingly crucial; I now believe it was the reason I couldn't get my code to work for days. To start, we need to add a name attribute to each of the input elements. The input elements should now look like this:

<input type="text" name = "parkName" placeholder = "Park Name">
<input type="text" name = "parkImage" placeholder="Image URL">

We'll use these parkName and parkImage attributes to tie this HTML to our index.js file. But more on that later. First, let's like to wrap up this HTML. The last thing we need to do to this file is wrap the button and two inputs in a form tag. Like so:

  <form action="/parks" method="POST">
        <p>Park Name: <input type="text" name = "parkName" placeholder = "Park Name"></p>
        <p>Park Picture: <input type="text" name = "parkImage" placeholder="Image URL"></p>
        <a href="/parks"><button>Add to My Memories</button></a>
    </form>

In the form attribute, we have denoted that this form will be used to post data onto the /parks page we created in the last article. That's what the <form action="/parks" method="POST"> bit of the above HTML does.

Back to the JavaScript

Adding the body-parser Middleware

To help with formatting our data, we need to download another npm package called data-parser. Let's go ahead and get this bit of housekeeping out of the way. As I showed in the first article when I installed Express, installing npm packages via the terminal is quite easy. Just type the command $npm i data-parser and the data-parser package downloads to your machine. Next, to let our code know we'd like it to use body-parser, we create the following variable at the top of the index.js file: const bodyParser = require("body-parser");. Then, to finish up body-parser set up, I enter the following code below my block of variables: app.use(bodyParser.urlencoded({extended: true}));. The area of my index.js file in which I've created all my variables to tell Node which packages I'm using now looks like this:

const express  = require("express");
const app = express();
const ejs = require("ejs");
const bodyParser = require("body-parser");
const http = require("http");
const port = 3000;

app.use(bodyParser.urlencoded({extended: true}));
app.set("view engine", "ejs");

Declaring a Globally Available Variable to Temporarily Store Data

Now that we have a way to parse the data, we need a place in our code where the data will be stored. Since I'm learning to code as I write this series, I don't yet know how to hook up this app to a database. For now, let's juse store the data we need (the name and an image URL for the parks we enter into the form created above) in a variable. It's important to note that this data will not persist, meaning once the server is shut down or restarted, all data entered into that variable is lost.

For this method of dealing with data to work, we need to make this variable globally accessible (meaning all the files in our app can get at it). To do so, let's create the variable above the first app.get function. The code looks like this:

const express  = require("express");
const app = express();
const ejs = require("ejs");
const bodyParser = require("body-parser");
const http = require("http");
const port = 3000;

app.use(bodyParser.urlencoded({extended: true}));
app.set("view engine", "ejs");

const visited = []

app.get("/", function(req, res){
   res.render("landing");
});

For now, let's leave visited as an empty array. Once we get all the pieces working together, we can go back and add in some data to push to the /parks pages. But, now we have a globally declared variable.

Logic for Parsing Data

The next step is to tweak the code to render the /parks page we wrote in the last article. As a reminder, that looked like this:

app.get("/parks", function(req, res){
    res.render("parks")
});

The tweaked code looks like this:

app.get("/parks", function(req, res){
    res.render("parks", {visited: visited})
});

The {visited: visited} portion we've added here tells body-parser to accept data that's in the same format as the array we labeled visited above.

Now that the /parks page has the middleware to parse the data we pass into it, we need to move from working with app.get functions and create an app.post function. This app.post will allow users to post data (right now, the name and an image of the parks they've visited) onto the /parks page.

In this POST function, we need to tell the /parks page what type of data it will be receiving from this request and add some logic to allow for new data to be created. To help the body-parser middleware and EJS pages communicate, let's add in three variables.

var name = req.body.parkName;
var image = req.body.parkImage;
var newPark = {name: name, image: image};

Here's what req.body means, per the body-parser docs:

A new body object containing the parsed data is populated on the request object after the middleware (i.e. req.body). This object will contain key-value pairs, where the value can be a string or array (when extended is false), or any type (when extended is true).

As for my newPark variable, this logic allows users to add in new parks to their page that conforms to the name and image schema we defined as part of the visited variable. With this newPark variable, we then need to write a quick bit of logic that will push data entered into the HTML form on the /landing page to appear on the /parks page. This logic looks like this: 

visited.push(newPark);

Now, we just need to wrap all this code into a POST request, like so: 

app.post("/parks", function(req, res){
   var name = req.body.parkName;
   var image = req.body.parkImage;
   var newPark = {name: name, image: image};
   visited.push(newPark);
   res.redirect("/parks");
});

The res.redirect bit at the bottom of the function tells the page to redirect to /parks once the logic above it has been carried out. 

Embedding JavaScript Into an EJS Page

The last little thing we need to do to get data to transfer between the two pages we've created is to embed a few lines of JavaScript into the parks.ejs file. For anyone familiar with vanilla JavaScript, the code will look very familiar, with just a little EJS spice. 

To use JavaScript in our EJS file, we need to use one of two demarcators, depending on what that line of JS is doing. For JavaScript that will not render on the page, the line of code needs to be book ended with these symbols: <% %>. For example:  <% visited.forEach(function(park){ %>. For lines of JavaScript that cause something to render on the DOM, the following bookends must be used: <%= %>. For example:  <%=park.name %>. Each line of JavaScript has to have one of these two symbols around it, or it will not work. 

Here's how this looks once it's put into the basic HTML of the parks.ejs file. 

<h2> The Parks I've Seen</h2>
<div>
  <% visited.forEach(function(park){ %>
    <img style="height: 200px; width: 200px;" src="<%= park.image %>">
    <p><%=park.name %></p>
  <%});%>
</div>

The above code runs a for...each loop (the function of which I denoted as park) through the visited variable I declared earlier. This for...each loop takes each image and name combination entered into the visited variable via the HTML form on the /landing page and displays them on the /parks page. 

Say the user entered in Yosemite and the URL for a particularly incredible image:

Image title

They'd then get this output: 

Image title

Whoo! It works! 

Conclusion

While we've got the logic working, it's still not super great looking. In the next article, we'll look at some ways to style the app so it doesn't look like something the kids from Stranger Things whipped up in their basement. To that, we'll add Boostrap into our app, make it fully responsive, and polish it up with a little CSS.  

Take a look at an Indigo.Design sample application to learn more about how apps are created with design to code software.

Topics:
web dev ,ejs ,node.js tutorial for beginners ,body-parser middleware ,web application development

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}