Cannot filter data based on variable that is outside of the EJS

49 views Asked by At

We are not able to combine retrieving the user's data abuot their interetsted country as a variable to filter the university database..

What we are trying to do here is:

  1. retrieve the user's data abuot their interetsted country (works)
<script>
        let UserCreds = JSON.parse(sessionStorage.getItem("user-creds"))
        let UserInfo = JSON.parse(sessionStorage.getItem("user-info"))

        country = UserInfo.interestedcountry;
        console.log(country);
</script>

  1. filter the university database based on a given location/country (works)
<div class="horizontalMobileScroll">
                <% const suggestedUniversities=universities.filter(row=> {
                    // Customize this condition based on your filtering criteria
                    let test = 'Belgium';
                    return row.location.includes(test);
                    });

                    suggestedUniversities.forEach(row => {
                    %>
                    <div class="horizontalMobileScroll__cell">
                        <div class="horizontalScroll">
                            <a href="<%= `/university/${row.id}` %>">
                                <img src="../../../statics/aalto-uni-logo.png"
                                    style="margin: 10px; width: 50px; height: auto;">
                                <h2 class="uniName">
                                    <%= row.name %>
                                </h2>
                                <h2 class="uniPlace">
                                    <%= row.location %>
                                </h2>
                            </a>
                        </div>
                    </div>
                    <% }); %>
            </div>
  1. combine both of that - the "country" from the user data will filter the suggested university database (does not work)

Why is that? Everytime we try to do something like below, it will output with "country is not defined"

<% const suggestedUniversities=universities.filter(row=> row.location.includes(country))
1

There are 1 answers

2
GreenSaiko On

The problem is, that you can incorporate ejs variables in JS code inside the <script> tags e.g. <script> var array = <%= universities %> </script>, but it's not possible the other way around e.g. <body> <% var location = country %> </body>. This is because, unlike the JavaScript inside a template which runs actively, the ejs parts are just filled in when the template is compiled.

Here is an example to understand better:

main.js

// imports

var PORT = 3000;

// ejs setup

const app = express(); //for simplicity I will be using express
const name = "Grax";
const job = "programmer";

app.get("*", (req, res) => {
  res.render("pages/someTemplate", {
    username: name,
    job: job
  });
});

const server = app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}\n`)
});

someTemplate.ejs

<!-- this works -->
<div id="first">
  <p>Hello! My name is <%= username %></p>
</div>

<!-- this works -->
<div id="second">
  <p id="paragraph"></p>
</div>

<!-- this does not work! -->
<% var userAge = age %>
<div id="third">
  <p><%= "I am " + userAge + " years old" %></p>
</div>

<script>
  var occupation = '<%= job %>'
  document.getElementById("paragraph").textContent = `I am a ${ occupation }`;

  var age = 21;
</script>

So we basically have here a main.js that runs the server and renders the someTemplate.ejs template. We pass the name and age to the compiler, it runs through the template and fills out any ejs tags with the values. Now after the compiler is done, the template will be sent to the host that send the request. The rendered page the user sees now, has no ejs tags in it, you can check on your app, but will obviously still contain all the html and js. So what once was Hello! My name is <%= username %> is now Hello! My name is Grax.

Now, to solve your issue, there are some possibilities:

  • Pass on the universities variable to a script (just like in the exampleTemplate var occupation = '<%= job %>'), do the filtering there, hardcode the HTML part of the listed universities and append it to the document
  • Download and add ejs on the client-side (you can see how on the official page) and either always render the whole template and pass it to the body or create a partial with the part where you render each university (suggestedUniversities.forEach(row => { %> <div class = "horizontalMobileScroll__cell"> ...) and just render this with the array passed to it and append it to the specific location you want it to be
  • send ajax requests to the server and do the rendering there, retrieve the rendered html code and again append it to the specific location

There could still be other possibilities, but theses are the ones I can name off the top of my head. You are welcome to ask for further explanation or examples. Good Luck!