CODE PAGE
EXPRESS
- Express is a Node framework for serving apps
- Express is the most popular Node package
- Express has many features such as HTTP get and post
- Express handles routing which is what to do with various inputs
- Express can use middleware apps to provide added functionality
EXPRESS APP
We will make an app that asks for a year and shows a result page with the Chinese zodiac animal for that year. There will be a static index page and a dynamic template result page. Express will handle the routing of the data to serve the right pages. Thanks Wendi Jollymore for the prototype.
- Follow the NODE INFO instructions to make an app called zodiac
- Make sure you are in VS Code with only the zodiac directory
- Make sure you have an app.js (empty is fine for now)
- Make sure you do the npm init
- Install Express. In the terminal type:
- Note the packages added to node_packages
- Note the change to the package.json
- We will also use a package to get the Chinese Animal of the Year
- And we will install nodemon for automatic refreshing
- We will use a Template Engine for our results page
- This will take data and insert it into our HTML
- There are different Engines - we will use EJS (Embedded JavaScript)
- Pay close attention to the folders we use as they change a few times!
- Make a folder called public in your zodiac folder
- Add an index.html to the public folder with the following code:
- Add an assets folder to your public folder
- Get the zodiac image from here ZODIAC JPG
- And put the image in your asset folder
- Add a zodiac.css page to your public folder with this code:
- Make a views folder in your zodiac folder NOT in the public folder
- Add a result.ejs page to the views folder with this code:
- Note the extension is ejs and not html and it is not in the public folder
- This is an html page where data will be inserted in the <%=variable %>
- Here are the types of EJS tags for reference
- There is no need to put them anywhere...
- Add the following code to the app.js page in the zodiac folder
- In the terminal (CTRL `) or pull up from bottom of VS Code
- Run the following code:
- Open the app in a browser at http://localhost:3000
- Choose a year and submit the form
- Note the comments in the terminal
// Install Express: npm i express
// Install Chinese-Year: npm i chinese-year // Install nodemon: npm i -D nodemon // in the package.json add the following to the scripts: // "start": "nodemon app.js" // remember to add a comma on the line before this
TEMPLATING
// Install EJS: npm i ejs
INDEX AND CSS PAGES
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Chinese Zodiac Animal</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="zodiac.css"> </head> <body> <header> <img src="assets/zodiac.jpg" alt="Chinese Zodiac Animals"> <h1>Chinese Zodiac Animal</h1> </header> <form action="getyear"> <p> <label for="year">Enter Year: <input type="number" max="4000" value="2024" name="year" id="year"> </label> </p> <input type="hidden" name="special" value="test special & normal characters!"> <p><input type="submit" value="Get Zodiac Animal"></p> </form> <footer> <img src="assets/zodiac.jpg" alt="Chinese Zodiac Animals"> </footer> </body> </html>
body { text-align: center; margin:20px; background-color:#b90b0c; font-family:'Lucida Sans'; } header { color:#eee; margin-bottom:30px } header img, footer img { margin:20px 0px 10px 0px; width:60%; min-width:400px; max-width:600px; } footer img { margin-top:40px } form { font-size:24px; background-color:rgb(255, 114, 114); display:inline-block; width:300px; padding:20px 30px; border:thick solid #ddd; border-radius:30px; } input { font-size:24px } input[type=submit] { padding:20px 40px; background-color: rgb(207, 0, 0); color:white; cursor:pointer; border-radius:10px; border:none; } input[type=submit]:hover { background-color: red; }
RESULT PAGE
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Results for Chinese Zodiac Animal</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="zodiac.css"> </head> <body> <header> <img src="assets/zodiac.jpg" alt="Chinese Zodiac Animals"> <br><br><br> <h1><%= year %> is the year of the <%= animal %></h1> </header> <footer> <img src="assets/zodiac.jpg" alt="Chinese Zodiac Animals"> </footer> </body> </html>
EJS TAGS
// EJS tags: <% %> // holds JavaScript but will not output <%= %> // outputs the value of content within <%- %> // outputs the content but escapes HTML charcters (use to output HTML) <%# %> // is a comment tag or just add a # to other tags to ignore them // the JavaScript tags can go around HTML and will connect up // which is nice for conditionals (seen below) and loops <% const message = "oh well"; // or perhaps from form data... const rand = Math.random(); if (rand > 0.8) { %> <h2>wow</h2> <% } else { %> <h2><%= message %></h2> <% } %>
APP PAGE
"use strict"; const express = require("express"); const app = express(); app.set("port", process.env.PORT || 3000); // set where static files such as html, images, css pages are located app.use(express.static('public')); // set how we will render to template files app.set("view engine", "ejs"); // bring in the chinese-year functionality const chineseYear = require("chinese-year"); // ROUTING // Routing is choosing what to do for various urls // In Express you can app.use(function) which uses the function to do something // This can also be used to call (mount) middleware (from other packages) // server requests can be routed with get(), post() - and others like all() // which are special versions of use() that capture get or post data // Route callbacks receive request (in), response (out) and next parameters // We can make our own callbacks // and if we do, they are responsible for calling next() // otherwise the flow will stop app.use((req, res, next)=>{ console.log(req.method + " request made to: " + req.url); // console.log(req.headers); next(); }); // PATH // Here we pass a path of "/test" to use() - regular expressions are allowed here too // This means, run this code if the URL starts with /test // note: app.get("/test") only runs if the url is exactly /test or with ? data after it // To test, run the app and in a browser use http://localhost:3000/test // this code will end the routing app.use("/test", (req, res, next)=>{ console.log("starting with test"); res.send("<h1>TEST</h1>"); res.end(); // do not go any further }); // GET AND POST // Below we check if we receive get or post data using routes that come with Express // we do this for /getyear which comes from the action of the form // (test by setting the form action=post to run the post code down below) // we could route other urls to and through different functions // ~~~~~~~~~~~~~~~~~ // GET app.get("/getyear", (req, res)=>{ // get data can be collected with req.query // this is an object with properties that match the names of the form fields console.log(req.query); const year = req.query.year ? req.query.year : new Date().getFullYear(); // get the animal from chinese-animal const animal = chineseYear.getAnimal(year); // this would send some html to the client // but we want to load the template page instead // // res.send("<h1>"+animal+"</h1>"); // just need result and not result.ejs // and pass it the data which is made available // to JavaScript on the template page res.render("result", {year:year, animal:animal}); // or just {year, animal} in ES6 }); // ~~~~~~~~~~~~~~~~~ // POST // When using POST - the data is in the body // Express's urlencoded method returns a function for the app to use // that will receive request, response and next parameters // then parse the data in the request, and add properties // that match the field names to the request body object // and then it calls next() app.use(express.urlencoded({extended:false})); // if collecting post data then this route will run app.post("/getyear", (req, res)=>{ // note we collect the year in the body - not the query console.log(req.body); const year = req.body.year ? req.body.year : new Date().getFullYear(); const animal = chineseYear.getAnimal(year); // use res.render() to render an ejs file res.render("result", {year:year, animal:animal}); // or {year, animal} in ES6 }); app.listen(app.get("port"), ()=>{ console.log("running on " + app.get("port")); });
RUNNING THE APP
// type the following and press Enter node app // or if nodemon is installed and in the "start" : "nodemon app.js" // is in the scripts of the package.json then type npm start
FULL Sheridan Node documentation can be found in Wendi Jollymore's Lessons.