I’m trying to make this post feature where the user can enter a number of names, and each name will be printed as a list item in ascending order like this:
-
-
Bruce Wayne
-
Peter Parker
-
Clark Kent
-
I’ve tried having an empty array, and then having the results of the form pushed onto the array, and have the computer print that name as a list-item, but it hasn’t worked. I just get the aforementioned problem.
Here’s my code:
JS part:
app.post("/submit", (req, res) => {
const clientName = req.body["fName"] + req.body["mName"] + req.body["lName"];
const nameList = [];
const characterName = nameList.push(clientName)
res.render("index.ejs", nameList, {
userName: clientName,
});
});
EJS part:
<% if (locals.userName) { %>
<ul>
<% for (let userName = 0; userName < locals.characterName; userName++) { %>
<li>
<%= nameList[userName] %>
</li>
<% } %>
</ul>
<% } else { %>
<p>No Names to Display</p>
<% } %>
2
Answers
Make that
const nameList = []
a global variable. Otherwise the data of the array will not be stored and gets destroyed everytime the get method at/submit
being called.Also it feels like you are missing the property
characterName
in the object you are passing in theres.render
function.Alright, there is a lot going on in your question.
First and foremost, as @David says in his comment, it’s not clear exactly what error you are encountering. Further, there are many decisions for the code logic that will not work this way. Let’s look at all the issues one after another:
(I know it’s a lot, but if you really want to understand what is happening and why, you should read through this)
1. Use of variables
The main issue of this code logic is that there is actually no variable storing the names. Just because you define the
nameList
variable asconst
doesn’t mean it is a globally available variable from this point on in any scope. What you are doing right now (as @Injamul is saying in his answer), is creating the list each time the request handler is invoked. Instead, what you should do, is to define thenameList
variable earlier in your code as a global variable.The
characterName
variable, on the other hand, is useless, as you can just saynameList.length
in the template. But in the end that comes down to personal preference. But at the very least, you need to pass the variable to the render function so it can be used. Which leads us to…2. Rendering EJS templates
The next big issue in your code is the (mis)use of variables in the context of rendering templates.
You seem to (somewhat?) know that variables you want to use in the EJS template need to be passed to the
render()
method. However, I simply cannot understand what led you to have 3 variables and handling each one different (you did not even passcharacterName
)?? The only variable that is properly passed to the function isclientName
. You need to pass any variable you want to use in the template in a single object, not as another parameter for therender()
method or any way else (except manually adding a variable to the locals context).This adds the variables to the locals context, which in the template then can be accessed either as just
someVariable
orlocals.someVariable
, it makes no difference (more on EJS variables and the locals context here).3. EJS template
The last problem is with your EJS template itself. In the definition of the
for()
loop you initialize a variable with the same name as a variable you passed to therender()
function:userName
. That means, up to the point where the for loop is,userName
was holding a string with the username, but once you (re)initialized that variable in the for loop asfor(let userName = 0...
its value changed to 0. So if you had passed all variables correctly to the render function (and made nameList a global variable),userName
would not be the last added name, but a number from 0 to the number of names saved. You should name that variable different, generally most people define a for loop asfor(let i = 0; i < someVariable; i++)
(orlet j
,let k
and so on).To sum everything up, making the current code you have running, it should look something like:
But ask yourself this: Is it really necessary making a post request and have the user load the page every time a name is added to the list?
Instead, you could manipulate the DOM by appending
<li>
items to the list, so something like: