0

I am working on a game and have run into a problem that I have been stuck on for hours. I have an object, and I want to write a loop which will take all the values in this object, and stick them into an html div. The way I am doing this is, I have taken a div, I am cloning it and giving all the child elements new values. Then I want to use the DOM manipulation to insert the values from one key, into a div with a heading and two paragraphs. Here is the code.

Index.html

<div id = "all_asset" style = "display: none;">
    <div class = "touch_box col-sm-12" style = "height: 150px; display: none;" id = "asset_touchbox">
        <br><h id = "asset_name"></h>
        <p1 id = "asset_price"></p1><hr>
        <p id = "asset_age"></p><hr>
    </div>    
</div>

play.js

function assetsList(){
    Object.keys(assets).forEach(key => {
        for (var i = 1; i < Object.keys(assets).length; i++){
    
            //duplicate box
            var list_box = document.getElementById("asset_touchbox");
            var clone_box = list_box.cloneNode(true);
            clone_box.id = "list_assets" + String(i);
            document.getElementById("all_asset").appendChild(clone_box);

            //get id of child elements
            clone_box.getElementsByTagName('h')[0].id = "asset_name" + String(i);
            clone_box.getElementsByTagName('p1')[0].id = "asset_price" + String(i);
            clone_box.getElementsByTagName('p')[0].id = "asset_age" + String(i);
            list_box.parentNode.appendChild(clone_box);
            //show box
            clone_box.style.display = "block";

            var asset_name = assets[key][0];
            var asset_age = assets[key][1];
            var asset_price = assets[key][2];

            document.getElementById("asset_name" + String(i)).innerHTML = asset_name;
            document.getElementById("asset_price" + String(i)).innerHTML = asset_age;
            document.getElementById("asset_age" + String(i)).innerHTML = asset_price;
        }
      });      
}

Javascript Object

//asset name, asset age, asset cost
assets = {1: ["Boat", 0, "10000"], 2: ["Carriage", 0, "10000"]}

So what I pretty much want to do is - Create two divs, each one has the information from each key. I hope I made sense. Please let me know if I didn't. Thanks!

0

3 Answers 3

1

Personally, I'd build the asset html inside your forEach function instead of cloning placeholder html. The code below should create the structure you're looking for. Good luck!

index.html

<div id="all_asset"/>

play.js

const assets = {
  1: ["Boat", 0, "10000"],
  2: ["Carriage", 0, "10000"]
}

function assetsList() {
  Object.keys(assets).forEach(key => {
    // get current asset data
    const assetData = assets[key];
    // create asset container
    const container = document.createElement("div");
    // create and append asset header
    const header = document.createElement('h1');
    header.appendChild(document.createTextNode(assetData[0]))
    // create and append first p
    const p1 = document.createElement('p')
    p1.appendChild(document.createTextNode(assetData[1]))
    // crreate and append second p
    const p2 = document.createElement('p')
    p2.appendChild(document.createTextNode(assetData[2]))
    // fill out the asset container
    container.appendChild(header)
    container.appendChild(p1)
    container.appendChild(p2)
    // append the whole thing to the parent
    document.getElementById("all_asset").appendChild(container);
  })
};
Sign up to request clarification or add additional context in comments.

Comments

1

You may want to consider refactoring your representation of the assets as an array of objects. For example,

let assets = [
  {
    name: 'boat',
    age: 0,
    price: 10000,
  },
  {
    name: 'carriage',
    age: 0,
    price: 10000,
  },
];

Following your initial idea of using the forEach method to iterate over the assets, you could dynamically insert a div for every asset.

assets.forEach(({ name, age, price }) => {
  let touchBox = document.createElement('div');
  touchBox.classList.add('touch_box', 'col-sm-12');
  touchBox.id = 'asset_touchbox';
  touchBox.style.height = '150px';

  let nameElt = document.createElement('h5');
  nameElt.id = 'asset_name';
  nameElt.innerHTML = name;

  let priceElt = document.createElement('p');
  priceElt.id = 'asset_price';
  priceElt.innerHTML = price;

  let ageElt = document.createElement('p');
  ageElt.id = 'asset_age';
  ageElt.innerHTML = age;

  touchBox.appendChild(nameElt);
  touchBox.appendChild(priceElt);
  touchBox.appendChild(ageElt);

  document.querySelector('#list_box').appendChild(touchBox);
});

Comments

1

You can use class to simplify the code.

Here is an example:

// The original object given by you
const givenAssets = {
  1: ['Boat', 0, '10000'],
  2: ['Carriage', 2, '30000']
};

// Get #all_asset
const assetContainer = document.querySelector('#all_asset');

// Define a class
class Asset {
  // Set parameters
  constructor(id, name, price, age) {
    this.id = id;
    this.name = name;
    this.price = price;
    this.age = age;
  }

  // Create HTML
  addHtml() {
    // HTML elements as string
    let html = `
      <div class="touch_box col-sm-12" id="list_asset${this.id}">
        <br>
        <h4 id="asset_name${this.id}">${this.name}</h4>
        <p id="asset_price${this.id}">${this.price}</p>
        <hr>
        <p id="asset_age${this.id}">${this.age}</p>
        <hr>
      </div>`;
      
    // Add HTML element before the end of #all_asset
    assetContainer.insertAdjacentHTML('beforeend', html);
  }
}

// Make instances and put them into an array
let assets = [];
for (const key in givenAssets) {
  assets.push(new Asset(key, givenAssets[key][0], givenAssets[key][1], givenAssets[key][2]))
}

// Execute .addHtml() on each asset one by one.
assets.forEach(asset => asset.addHtml());
<div id="all_asset"></div>

4 Comments

I didn't use your original object assets = {1: ["Boat", 0, "10000"], 2: ["Carriage", 0, "10000"]}. If you want to use it, let me know. Then I'll modify my code.
Yes, actually. That would be really great.
I did it. Check it please ;)
I removed the .replace() part of let html. Values can be passed into the string directly because of template literal ``.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.