Home > database >  Persist data sent to a Pug template via render
Persist data sent to a Pug template via render

Time:10-15

I'm trying to find out how I can persist the data I pass to my Pug template from the Express render method.

I pass in some JSON data to the res.render() method in Express that renders my view with Pug. On the Pug template, I use that data immediately to populate one of my select elements with drop down values from the JSON data.

What I want to then do is store this data that was passed so I can use it in an event handler function I create for another field.

Basically, I'm passing a table name and the field names for the table, but for each table I have in the JSON data.

So the shape is like [{ tableName: "table name here", fieldNames: ['field1', 'field2', ...] }, ... ]

I have a select field for "choose a table name" and when the user picks a table name, I then want to get the fieldNames for a second select field that allows them to choose a field name to use. So I have an event handler setup on the "choose a table name" field that runs a little event handler I have setup in the pug template. Only problem is the event handler does not have access to the data that was passed to the Pug template originally.

I'm trying to google this but having no luck finding anything, so does anyone know how I can persist data sent via the res.render() method in a pug template for using after the page has been rendered inside an event handler or other functions?

Thank you!

CodePudding user response:

Always be clear what is done at the server (pug) and what is done in client Javascript (browser).

While data passed to pug scripts are meant to be consumed at the server, it is possible to inject, for want of a better word, server data into client side Javascript variables.

The following creates two dropdown lists on the same page using the exact same data passed by Express. One is generated at the server, while the second is created entirely by Javascript running in the browser.

Express code:

app.get("/testdata", (req, res) => {
  res.render("testdata", { data: [ 1, 2, 3, 4, 5]});
});

testdata.pug:

html
  head
  body 
    p Dropdown list generated at the server:
    p 
      select  
        each n in data 
          option(value=n)=n
          br

    p Dropdown list generated in browser Javascript: 
    p 
      select#dropdown

  script.
    document.body.onload = () => {
      const dropdown = document.getElementById("dropdown");
      let data = JSON.parse("#{JSON.stringify(data)}"); // line 18
      data.forEach(d => {
        const item = document.createElement("option");
        item.innerText = d;
        dropdown.appendChild(item);
      })
    }

I have used the same variable name in totally different contexts pointing to different entities. Be careful not to trip. For example, look at line 18:

   let data = JSON.parse("#{JSON.stringify(data)}"); // line 18
  1. The first instance of data is a Javascript variable in the browser.
  2. The second instance of data is a server object passed to the pug script in the render method. Basically any #{expression} instances found in a pug file are evaluated¹ when the view is rendered.

¹ I think the expression is evaluated and its toString method called. If I know it is an array, I could have used:

  let data = [#{data}]; // line 18
  • Related