String template literal with Object.keys.map

I have a JSON object that I am trying to output as HTML by creating a function that returns a String template literal that iterates over the JSON and creates a list of properties and values from the JSON, but the returned value is a comma for every iteration (there are 12 iterations), what is wrong with my syntax that would cause this?

const createSubmissionHtml = () => {
  return `
  <!DOCTYPE html>
    <html>
        <head>
        <title>Form Submissions</title>
        </head>
        <body>
            ${Object.keys(JsonObj).map((key) => {
              console.log(JsonObj[key]);
              let submission = JsonObj[key];
              `<div class="submission"><ul>`;
              Object.entries(submission).map((entry) => {
                const [prop, value] = entry;
                `<li>${prop}: ${value}</li>`;
              });
              `</ul></div>`;
            })}
        </body>
    </html>`;
};

Doing this from my phone so cant test this. Two things. Missing a return and finally joining the array.

Object.entries(submission).map((entry) => {
        const [prop, value] = entry;
        return `<li>${prop}: ${value}</li>`;
 }).join('\n');

Hopefully thats it.

Thanks, but I am still only getting the 12 commas in the list. Why would I need to return? the map() function returns an array by itself correct? Also, would it matter that most of the properties have spaces and question marks, and that some of the values are URLs within the JSON?

I can console.log(<li>${prop}: ${value}</li>) and see the correct output, but the file I am creating using the “fs” module, only has the other HTML around ‘,’. like this:


  <!DOCTYPE html>
    <html>
        <head>
        <title>Form Submissions</title>
        <link src="./css/submissions.css">
        </head>
        <body>
            ,,,,,,,,,,,
        </body>
    </html>

Not when it’s inside curly brackets.

[1,2,3].map((num) => {
  num * 2
});
// [undefined, undefined, undefined]

[1,2,3].map((num) => {
  return num * 2
});
// [2,4,6]

// Without curly braces values returned
[1,2,3].map((num) => num * 2);
// [2,4,6]

Can you provide a sample of the json object?

Maybe that’s why I am not seeing the <div class="submission"><ul>; in the first map. I can’t share the csv/JSON, as it has private data, but like I said, the console.log(<li>${prop}: ${value}</li>); displays all the correct properties and values, so I don’t understand why the following return <li>${prop}: ${value}</li>; doesn’t display in the returned HTML.

const createSubmissionHtml = (JsonObj) => {
  return `
  <!DOCTYPE html>
    <html>
        <head>
        <title>Form Submissions</title>
        <link src="./css/submissions.css">
        </head>
        <body>
            ${Object.keys(JsonObj).map((key) => {
              let submission = JsonObj[key];
              `<div class="submission"><ul>`;
              Object.entries(submission)
                .map((entry) => {
                  const [prop, value] = entry;
                  console.log(`<li>${prop}: ${value}</li>`);
                  return `<li>${prop}: ${value}</li>`;
                })
                .join("\n");
              `</ul></div>`;
            })}
          </body>
        </html>
      `;
};

Again there appears to be a missing return there and the list items need to be contained within that string

let submission = JsonObj[key];
return `
<div class="submission">
    <ul>
        ${Object.entries(submission)
            .map((entry) => {
                ...
                return `<li>${prop}: ${value}</li>`
            }
        }
    </ul>
</div>
`
1 Like

I don’t know how this compares to the format of your json object, but I had a play around with some sample data.

const users = {
  '01': {
    name: 'Leanne Graham',
    username: 'Leanne',
    email: 'leanne.g@april.biz'
  },
  '02': {
    name: 'Ervin Howell',
    username: 'Ervin',
    email: 'ervin.howell@melissa.tv'
  },
  '03': {
    name: 'Clementine Bauch',
    username: 'Clementine',
    email: 'clementine@yesenia.net'
  },
  '04': {
    name: 'Patricia Lebsack',
    username: 'Patricia',
    email: 'patricia.lebsack@kory.org'
  }
}

function parseToLists (json, className) {
  const lists = Object.values(json) // not interested in the keys

  return lists.map((entry) => (
`
    <div class='${className}'>
       <ul>
        ${
          Object
            .entries(entry)
            .map(([prop, value]) => (
              `\t<li>${prop}: ${value}</li>`
            ))
            .join('\n\t\t')
        }
       </ul>
    </div>`
  )).join('\n')
}

console.log(parseToLists(users, 'submission'))

I am using parentheses to wrap the return values from the arrow functions e.g.

['a', 'b', 'c'].map((char) => (
    char.toUpperCase() // will be returned
)) 
// ['A', 'B', 'C' ]

I think it is a bit cleaner this way for template strings.

Note the \t\n’ are tab and newline and are just for presentation.

codepen

Thanks, SOO much!! It was the missing the returns on the map functions. It is working great now. You are a lifesaver, and I learned something too. Have a great evening!

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.