JavaScript Express Basics Parameters, Query Strings, and Modularizing Routes Linking Around the Application

Sean Flanagan
Sean Flanagan
33,218 Points

The Next card link

Hi. I clicked on the Next card link but the page won't work and localhost isn't sending any data.

app.js:

const express = require("express");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");

const app = express();

app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());

app.set("view engine", "pug");

const mainRoutes = require("./routes");
const cardRoutes = require("./routes/cards");

app.use(mainRoutes);
app.use("/cards", cardRoutes);

app.use((err, req, res, next) => {
  res.locals.error = err;
  res.status(err.status);
  res.render("error", err);
});

app.listen(3000, () => {
  console.log("The application is running on localhost:3000!");
});

index.pug:

extends layout.pug

block content
  section#content
    p
      a(href="/cards") Begin!

card.pug:

extends layout.pug

block content
  section#content
    h2= text
    if hint
      p
        i Hint: #{hint}
    a(href=`${id}?side=${sideToShow}`)= sideToShowDisplay
    br
    a(href="/cards") Next card

layout.pug:

doctype html
html(lang="en")
  head
    title Flash Cards
  body
    include includes/header.pug
    if name
      h2 Welcome, #{name}!
      form(action="/goodbye", method="post")
        button(type="submit") Goodbye
    block content
    include includes/footer.pug

goodbye.pug:

extends layout

block content
  form(action="/goodbye", method="post")
    button Goodbye!

error.pug:

extends layout

block content
  h1= error.message
  h2= error.status
  pre= error.stack

I would appreciate any help please.

32 Answers

Natalie Cluer
Natalie Cluer
18,884 Points

ooo wait!

router.get("/:id", (req, res) => {
  const {side} = req.query;
  const {id} = req.params;

  if (!side) {
    res.redirect("/cards/${id}?side=question");
  }

you are trying to access the value of id in the redirect, but you aren't using a template literal. could that be it?

Natalie Cluer
Natalie Cluer
18,884 Points

ok think i found the problem:

router.get("/:id", (req, res) => {
  const {side} = req.query;
  const {id} = req.params;

  if (!side) {
    res.redirect("/cards/${id}?side=question");
  }

in your route handler here you are setting const {id} to req.params. this should be set to req.params.id

let me know if that works!

Natalie Cluer
Natalie Cluer
18,884 Points

Hi Sean! can we see the routes file?

Sean Flanagan
Sean Flanagan
33,218 Points

Hi Natalie.

My index.js:

const express = require("express");
const router = express.Router();

router.get("/", (req, res) => {
  const name = req.cookies.username;
  if (name) {
    res.render("index", {name});
  } else {
    res.redirect("/hello");
  }
  res.render("index", {name: name});
});

router.get("/hello", (req, res) => {
  const name = req.cookies.username;
  if (name) {
    res.redirect("/");
  } else {
    res.render("hello");
  }
});

router.post("/hello", (req, res) => {
  res.cookie("username", req.body.username);
  res.redirect("/");
});

router.post("/goodbye", (req, res) => {
  res.clearCookie("username");
  res.redirect("/hello");
});

//router.use((req, res, next) => {
//  const err = new Error("Not Found");
//  err.status = 404;
//  next(err);
//});

module.exports = router;

cards.js:

const express = require("express");
const router = express.Router();
const {data} = require("../data/flashcardData.json");
const {cards} = data;

router.get("/", (req, res) => {
  const numberOfCards = cards.length;
  const flashcardId = Math.floor(Math.random() * numberOfCards);
  res.redirect(`/cards/${flashcardId}`);
});

router.get("/:id", (req, res) => {
  const {side} = req.query;
  const {id} = req.params;

  if (!side) {
    res.redirect("/cards/${id}?side=question");
  }

  const name = req.cookies.username;
  const text = cards[id][side];
  const {hint} = cards[id];

  const templateData = {id, text, name};

  if (side === "question") {
    templateData.hint = hint;
    templateData.sideToShow = "answer";
    templateData.sideToShowDisplay = "Answer";
  } else if (side === "answer") {
    templateData.sideToShow = "question";
    templateData.sideToShowDisplay = "Question";
  }

  res.render("card", templateData);
});

module.exports = router;
Natalie Cluer
Natalie Cluer
18,884 Points

so to render the next card the link route should be /cards/:id, but your link in the pug file is only to /cards

Natalie Cluer
Natalie Cluer
18,884 Points

are there any errors in your terminal?

Sean Flanagan
Sean Flanagan
33,218 Points

Hi Natalie. Thanks for your help so far.

I added .id to the end of that line.

It's still not working. The error message in my terminal is:

RangeError: Invalid status code: undefined

Natalie Cluer
Natalie Cluer
18,884 Points

hey Sean! sorry I disappeared! (Easter and all) what url are you using to access the page? also, in the same route I mentioned earlier, I think you might have to use req.query.side, not just req.query

Adam Beer
Adam Beer
11,267 Points

Hello Sean. Natalie find your problem. The wrong in the cards.js section of res.redirect(/cards/${flashcardId}?side=question). You lost the query string. Have a nice day!

Sean Flanagan
Sean Flanagan
33,218 Points

Hi Natalie and Adam. Thank you both for replying. I took Easter off as well so no problem. And Natalie, I appreciate your help.

I'm very sorry but it's still not working. Is this what you were talking about?

router.get("/", (req, res) => {
  const numberOfCards = cards.length;
  const flashcardId = Math.floor(Math.random() * numberOfCards);
  res.redirect(`/cards/${flashcardId}?side=question`);
});

I typed in the URL http://localhost:3000/cards/ and http://localhost:3000/cards/3?side=question.

The message I got was:

Flash Cards
Not Found
404
Error: Not Found
    at router.use (C:\Users\user\Desktop\treehouse\routes\index.js:34:15)
    at Layer.handle [as handle_request] (C:\Users\user\Desktop\treehouse\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (C:\Users\user\Desktop\treehouse\node_modules\express\lib\router\index.js:317:13)
    at C:\Users\user\Desktop\treehouse\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (C:\Users\user\Desktop\treehouse\node_modules\express\lib\router\index.js:335:12)
    at next (C:\Users\user\Desktop\treehouse\node_modules\express\lib\router\index.js:275:10)
    at Function.handle (C:\Users\user\Desktop\treehouse\node_modules\express\lib\router\index.js:174:3)
    at router (C:\Users\user\Desktop\treehouse\node_modules\express\lib\router\index.js:47:12)
    at Layer.handle [as handle_request] (C:\Users\user\Desktop\treehouse\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (C:\Users\user\Desktop\treehouse\node_modules\express\lib\router\index.js:317:13)
An app to help you study

Nothing came up in the command prompt.

I looked at my index.js file and found this:

router.use((req, res, next) => {
  const err = new Error("Not Found");
  err.status = 404;
  next(err);
});
Natalie Cluer
Natalie Cluer
18,884 Points

try putting that error block in app.js just above your general error handler

Adam Beer
Adam Beer
11,267 Points

In index.js please cut the last router.use((req, res, next) function and past into app.js file from the bottom to the third place.

Sean Flanagan
Sean Flanagan
33,218 Points

I've put the router.use block in the app.js file, third from the bottom. The block immediately below that is

app.use((err, req, res, next) => {
  res.locals.error = err;
  res.status(err.status);
  res.render("error", err);
});

Immediately above the router.use block:

app.use(mainRoutes);
app.use("/cards", cardRoutes);
Adam Beer
Adam Beer
11,267 Points

I don't understand but i uploaded my solution on github. https://github.com/trAApex/mysolution

Sean Flanagan
Sean Flanagan
33,218 Points

Sorry Adam, a typo on my part. I've edited my last post. Thank you.

Adam Beer
Adam Beer
11,267 Points

So your code is run? I will not give up. I will find the error in code.

Sean Flanagan
Sean Flanagan
33,218 Points

Hi @adambeer. It's still not running. In the prompt, the error message:

ReferenceError: router is not defined
at app.js:19:1

Now here's the line in question:

router.use((req, res, next) => { // <== This line
  const err = new Error("Not Found");
  err.status = 404;
  next(err);
});

I'm looking at your code now and comparing it with mine. I've noticed some differences between our respective app.js files.

Here's mine:

const express = require("express");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");

const app = express();

app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static("public"));

app.set("view engine", "pug");

const mainRoutes = require("./routes");
const cardRoutes = require("./routes/cards");

app.use(mainRoutes);
app.use("/cards", cardRoutes);

router.use((req, res, next) => {
  const err = new Error("Not Found");
  err.status = 404;
  next(err);
});

app.use((err, req, res, next) => {
  res.locals.error = err;
  res.status(err.status);
  res.render("error", err);
});

app.listen(3000, () => {
  console.log("The application is running on localhost:3000!");
});

And yours:

const express = require('express');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');

const app = express();

app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());

// tells express which template engine to use
app.set('view engine', 'pug');
app.use('/static', express.static('public'));

const mainRoutes = require('./routes');
const cardRoutes = require('./routes/cards');

app.use(mainRoutes);
app.use('/cards', cardRoutes);

app.use((req, res, next) => {
    const err = new Error('Not Found');
    err.status = 404;
    next(err);
});

app.use((err, req, res, next) => {
    res.locals.error = err;
    res.status(err.status);
    res.render('error', err);
});

app.listen(3000, () => {
    console.log('The application is running on localhost:3000');
});

Your solution, is it the final product? Have you finished this course? I only ask because I haven't.

Adam Beer
Adam Beer
11,267 Points

Yes, I've finished course. This is the final product.

Adam Beer
Adam Beer
11,267 Points

Please fix the router.use function to app.use

Sean Flanagan
Sean Flanagan
33,218 Points

Adam Beer Done.

RangeError: Invalid status code: undefined

Adam Beer
Adam Beer
11,267 Points

You do not need the goodbye.pug file. You copied it into the layout.pug file. And delete your eleventh rows in app.js. Unnecessary the res.render("index", {name: name}); . I can't see anything else difference. I used ' ' and not " " but this isnt problem. And now don't work?

Sean Flanagan
Sean Flanagan
33,218 Points

Hi Adam. Thanks for your help. I've deleted the goodbye.pug file and the res.render line. Still the same error as before.

Adam Beer
Adam Beer
11,267 Points

Hi Sean! Please upload your project files to github. I check it.

Adam Beer
Adam Beer
11,267 Points

Search your folder with git bash.You get in. In your folder use git init command, after use git add command and add your folders one by one without node_modules folder. After git commit -m "Your message". And now make new repository in github and copy the link. Now in git bash use gut remote add origin (+ your repository url), after git push -u origin master. And then you uploaded yours files to gitfub. And please share your link.

Sean Flanagan
Sean Flanagan
33,218 Points

Hi. I've opened the git bash. I added the folder I'm using. I can't add the files inside it.

Here's the link:

https://github.com/SeanFl42/Treehouse-Express-Basics.git

Guil Hernandez
STAFF
Guil Hernandez
Treehouse Teacher

Hi Sean Flanagan!

It looks like the GitHub repository you linked to is empty. Could you please update it with the latest files so I can have a look and help out? :)

Sean Flanagan
Sean Flanagan
33,218 Points

Hi Guil.

I've tried updating the repository but I don't know how to.

I typed in

git add app.js

and I got

fatal: Unable to create 'C:/Users/user/.git/index.lock': File exists.

Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. Please make sure all processes
are terminated then try again. If it still fails, a git process
may have crashed in this repository earlier:
remove the file manually to continue.
Adam Beer
Adam Beer
11,267 Points

Hi Sean. Please use git log. What does it happened?

Guil Hernandez
STAFF
Guil Hernandez
Treehouse Teacher

Sean Flanagan,

Deleting index.lock usually solves this issue. Check out this post. You could also zip up your files and email them to me at guil@teamtreehouse in the meantime.

Sean Flanagan
Sean Flanagan
33,218 Points

I tried

git log app.js

Output:

fatal: your current branch 'Stage4Video1' does not have any commits yet

Stage4Video1 is Stage 4 Video 1 of the Gulp Basics course:

https://teamtreehouse.com/library/putting-multiple-tasks-together

Guil Hernandez
STAFF
Guil Hernandez
Treehouse Teacher

Hey Sean Flanagan,

I think your issue is here:

if (!side) {
  res.redirect("/cards/${id}?side=question");
}

The path inside res.redirect() should be a template literal. Try replacing the double quotes with backticks. Let me know if that works for you. :)

if (!side) {
  res.redirect(`/cards/${id}?side=question`);
}
Sean Flanagan
Sean Flanagan
33,218 Points

Hi Guil.

Output:

RangeError: Invalid status code: Undefined
Guil Hernandez
STAFF
Guil Hernandez
Treehouse Teacher

Thanks for posting the output. To get past the error, try this modification to your error route handler in app.js:

app.use((err, req, res, next) => {
  res.locals.error = err;
    if (err.status) {
      res.status(err.status);
    }
    res.render('error', err);
});

That could help prevent that RangeError when the status code is undefined. Let me know what the output is after that.

Sean Flanagan
Sean Flanagan
33,218 Points

Hi Guil.

I typed in the URL http://localhost:3000/cards/undefined?side=question and got a very long series of error messages in the command prompt.

Error: can't set headers after they are sent.
Adam Beer
Adam Beer
11,267 Points

Hi Sean! Check this link. How do you make new repo and upload your files to GitHub. It is just few minutes. https://www.youtube.com/watch?v=9RqXo6VD-jw