0

I have a JSON object with different cars, I am relaying these cars to HTML with a loop, however whenever I try to make the condition (<=) above 10, it throws an error.

This is for a test I am making with a cars site.

Here is my function:

function dispCars(){
    let output = "";
    let i = 1;
    let maxNum = 10;
    while (i <= maxNum){
      const carName = cars["c" + i].name;
      const carMake = cars["c" + i].make;
      const carPrice = cars["c" + i].price;
      console.log(carName);
      output += "<div class='column'><div style='padding:0px;' class='ui segment'><a href='#'><img class='card-icon' src='../src/media/cars/" + i + ".jpg'></a><a href='#'><p class='heading'>"+ carMake + " " + carName + "</a><span class='price'>" + carPrice + "</span></p></div></div></div>";
      i++;
    }

    catalogue.innerHTML = output;
}

Here is a little bit of JSON:

const cars = {
    "c1": {
        "id": 1,
        "name": "Sprinter Boxtruck",
        "make": "Mercedes",
        "price": "£500,000",
        "topspeed": "87mph",
        "vip": "false"
    },
    "c2": {
        "id": 2,
        "name": "RS4 Avant",
        "make": "Audi",
        "price": "£300,000",
        "topspeed": "101mph",
        "vip": "false"
    },
    "c3": {
        "id": 3,
        "name": "250 GTO",
        "make": "Ferrari",
        "price": "£350,000",
        "topspeed": "92mph",
        "vip": "false"
    },
    "c4": {
        "id": 4,
        "name": "Enzo",
        "make": "Ferrari",
        "price": "£3,500,000",
        "topspeed": "130mph",
        "vip": "false"
    }
    ,
    "c5": {
        "id": 5,
        "name": "F350 Superduty",
        "make": "Ford",
        "price": "£500,000",
        "topspeed": "80mph",
        "vip": "false"
    },
    "c6": {
        "id": 6,
        "name": "Focus SVT",
        "make": "Ford",
        "price": "£250,000",
        "topspeed": "81mph",
        "vip": "false"
    },
    "c7": {
        "id": 7,
        "name": "Mustang GT",
        "make": "Ford",
        "price": "£800,000",
        "topspeed": "87mph",
        "vip": "false"
    },
    "c8": {
        "id": 8,
        "name": "Raptor SVT",
        "make": "Ford",
        "price": "£500,000",
        "topspeed": "70mph",
        "vip": "false"
    },
    "c9": {
        "id": 9,
        "name": "Transit",
        "make": "Ford",
        "price": "£150,000",
        "topspeed": "87mph",
        "vip": "false"
    }
    ,
    "10": {
        "id": 10,
        "name": "E-Type",
        "make": "Jaguar",
        "price": "£250,000",
        "topspeed": "87mph",
        "vip": "false"
    },
    "c11": {
        "id": 11,
        "name": "F-Type",
        "make": "Mercedes",
        "price": "£600,000",
        "topspeed": "99mph",
        "vip": "false"
    },
    "c12": {
        "id": 12,
        "name": "Gallardo",
        "make": "Lamborghini",
        "price": "£2,500,000",
        "topspeed": "111mph",
        "vip": "false"
    },
...

Here is the error thrown:

index.js:29 Uncaught TypeError: Cannot read property 'name' of undefined
    at dispCars (index.js:29)
    at index.js:40

My expected result is for the output to correspond with the input, e.g. if I make the condition <=12 I want it to relay 12 cars to HTML. It works like that perfectly well when the condition is below 10. Actual result is an error thrown.

tzcoding
  • 69
  • 6

1 Answers1

1

Use an array, not an object:

const cars = [
    {
        "id": 1,
        "name": "Sprinter Boxtruck",
        "make": "Mercedes",
        "price": "£500,000",
        "topspeed": "87mph",
        "vip": "false"
    },
    {
        "id": 2,
        "name": "RS4 Avant",
        "make": "Audi",
        "price": "£300,000",
        "topspeed": "101mph",
        "vip": "false"
    },
    // ...
];

and then use a for loop, a for-of loop, forEach, map, or some other array looping construct. Since you're using ES2015+ features, for-of would be the minimal change. You can even use destructuring and perhaps a template literal:

function dispCars(){
    let output = "";
    for (const [index, {name, make, price}] of cars.entries()) {
      output += `<div class='column'><div style='padding:0px;' class='ui segment'><a href='#'><img class='card-icon' src='../src/media/cars/${index + 1}.jpg'></a><a href='#'><p class='heading'>${make} ${name}</a><span class='price'>${price}</span></p></div></div></div>`;
    }
    catalogue.innerHTML = output;
}

but I'd probably go a bit further and use map and join:

function dispCars(){
    catalogue.innerHTML = cars.map((index, {name, make, price}) =>
      `<div class='column'><div style='padding:0px;' class='ui segment'><a href='#'><img class='card-icon' src='../src/media/cars/${index + 1}.jpg'></a><a href='#'><p class='heading'>${make} ${name}</a><span class='price'>${price}</span></p></div></div></div>`
    ).join("");
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875