5

I ran into a problem and couldn't fix it today. For example, there is a json file text.json

[
  {
    "id":1,
    "name":"Jon",
    "email":"John@gmail.com"
  },
  {
    "id":2,
    "name":"Sam",
    "email":"Sam@gmail.com"
  },
  {
    "id":3,
    "name":"Dan",
    "email":"Dan@gmail.com"
  }
]

Now I want to use ajax to get this json file and here is the part doesn't work.

let output = users.map((i) => {
                    return `<ul>
                        <li>ID: ${users.id} </li>
                        <li>Name: ${users.name}</li>
                        <li>Email: ${users.email}</li>
                    </ul>`
                })

Where should I put the i in template literals ?

Mörre
  • 5,699
  • 6
  • 38
  • 63
Cho Lin Tsai
  • 87
  • 1
  • 1
  • 10
  • You should use `i.propName` instead of `users.propName` – Titus Oct 03 '17 at 12:44
  • Also note that proper JSON is a key/value format and should start with "{ someKey : ..." not with "[", although the array hack is used a lot it may cause problems in various frameworks and libs. – Christophe Roussy Oct 03 '17 at 12:45
  • @ChristopheRoussy JSON is a **string** format! And of course it can contain a serialized array! To OP: You have an **Array** object, not a JSON **string**. The entire question is after the network request part - you already _have_ the array. "JSON" and "Ajax" are not part of your question - tags removed. – Mörre Oct 03 '17 at 12:47
  • Not related to your question, but you can make your arrow function shorter by dropping parentheses around a single argument and using an expression as an implicit return instead of brackets and a `return` statement: `users.map(i=>\`...\`)` – apsillers Oct 03 '17 at 12:48
  • @ChristopheRoussy JSON can be an array or an object (or, in fact, a number or a string or a boolean, too); this is an array. Why do you think arrays can't be top-level objects in a JSON document? Please take some time and review the grammar on http://www.json.org/ – apsillers Oct 03 '17 at 12:51
  • thanks guys, all suggestions are really helpful! – Cho Lin Tsai Oct 03 '17 at 12:52
  • @apsillers hmmm there used to be issues with the array form, and a good practice was to use an object around the array (also to add meta data later), those problems seem to be quite old now: https://stackoverflow.com/questions/3833299/can-an-array-be-top-level-json-text, I would say arrays are valid but object is more wide spread and has better support in parsers across various languages/libs/frameworks. – Christophe Roussy Oct 03 '17 at 13:48

5 Answers5

10

Wouldn't it be:

let output = users.map((i) => {
    return `<ul>
              <li>ID: ${i.id} </li>
              <li>Name: ${i.name}</li>
              <li>Email: ${i.email}</li>
            </ul>`;
 });
danwellman
  • 9,068
  • 8
  • 60
  • 88
  • happy to help :) – danwellman Oct 03 '17 at 12:49
  • @ChoLinTsai Please declare an answer then, so that others browsing the list of issues know that your has already been solved :-) The answer from Andrzej Smyk has the advantage of giving you bette naming, you should not use "i" because by convention that is used for numeric indexes. That is programmer culture, not technical, but it helps when people work together to stick to such conventions when you have no reason not to. – Mörre Oct 03 '17 at 13:00
6

You're trying to access the value on the parent array as oppose to each individual element in the array.

Try this instead:

users.map(user => 
  `<ul>
    <li>ID: ${user.id} </li>
    <li>Name: ${user.name}</li>
    <li>Email: ${user.email}</li>
  </ul>`
);
3

Template literal should be of form ${i.id} etc. You want to render template with values of processed items not the users array. users does not have properties id or email, so these are undefined

const users = [
  {
    "id":1,
    "name":"Jon",
    "email":"John@gmail.com"
  },
  {
    "id":2,
    "name":"Sam",
    "email":"Sam@gmail.com"
  },
  {
    "id":3,
    "name":"Dan",
    "email":"Dan@gmail.com"
  }
];

const output = users.map(({ id, name, email }) => {
    return `<ul>
        <li>ID: ${id} </li>
        <li>Name: ${name}</li>
        <li>Email: ${email}</li>
    </ul>`
});

console.log(output);
Andrzej Smyk
  • 1,684
  • 11
  • 21
1

In your lambda, you are using i to reference each user, thus, you need to use i.id, i.name, etc.:

let users = [
  { "id":1, "name":"Jon", "email":"John@gmail.com" },
  { "id":2, "name":"Sam", "email":"Sam@gmail.com" },
  { "id":3, "name":"Dan", "email":"Dan@gmail.com" }
];

let output = users.map((i) => {
  return `<ul>
            <li>ID: ${i.id}</li>
            <li>Name: ${i.name}</li>
            <li>Email: ${i.email}</li>
          </ul>`;
});

console.log(output);
Sumner Evans
  • 8,951
  • 5
  • 30
  • 47
0

You should use 'i' variable to access to object properties:

users.map((i) => {
  return `<ul>
         <li>ID: ${i.id} </li>
         <li>Name: ${i.name}</li>
         <li>Email: ${i.email}</li>
      </ul>`
})
Artem Kolodko
  • 410
  • 2
  • 10