Dynamic bootstrap cards with javascript

Viewed 34

I have here a json file and this content should get rendered inside of bootstrap cards.

[{
    "scripts": {
        "web3py": [
            {
                "thumbnail": "images/thumbnails/sendetherweb3py.png",
                "scriptName": "send Native",
                "description": "send native with web3py",
                "link": "https://jsonformatter.org/img/tom-cruise.jpg"
            },
            {
                "thumbnail": "images/thumbnails/sendtokenweb3py.png",
                "scriptName": "send token",
                "description": "send erc20 token with web3py",
                "link": "https://jsonformatter.org/img/tom-cruise.jpg"
            },
            {
                "thumbnail": "images/thumbnails/swapnativeweb3py.png",
                "scriptName": "swap native token dex",
                "description": "swap eth for erc20 token",
                "link": "https://jsonformatter.org/img/tom-cruise.jpg"
            },
            {
                "thumbnail": "images/thumbnails/swaptokenweb3py.png",
                "scriptName": "swap erc20 token on dex",
                "description": "swap erc20 token with erc20 token",
                "link": "https://jsonformatter.org/img/tom-cruise.jpg"
            }
        ],
        "web3js": [
            {
                "thumbnail": "images/thumbnails/swaptokenethers.png",
                "scriptName": "swap token on dex",
                "description": "swap erc20 token with token on a dex",
                "link": "https://jsonformatter.org/img/tom-cruise.jpg"
            },
            {
                "thumbnail": "images/thumbnails/swapnativeethers.png",
                "scriptName": "swap native",
                "description": "swap native for token on dex",
                "link": "https://jsonformatter.org/img/tom-cruise.jpg"
            },
            {
                "thumbnail": "images/thumbnails/sendtokenethers.png",
                "scriptName": "send ERC20 token",
                "description": "send erc20 token with ethers",
                "link": "https://jsonformatter.org/img/tom-cruise.jpg"
            },
            {
                "thumbnail": "images/thumbnails/sendnativeethers.png",
                "scriptName": "send native",
                "description": "send Native ETH with ethers",
                "link": "https://jsonformatter.org/img/tom-cruise.jpg"
            }
        ]
    }
}]

Inside scripts I have 2 categories, web3py and web3js with 4 items in it. Now i want to render web3py inside a row that than contains 4 cards and another row web3js that contains also 4 cards.

How can I render bootstrap cards in Javscript based on the content from my json file?

I want to do this dynamically so in case i add more items to web3py or web3js, i want the cards to be created dynamically.

So what would be the best way to create those 4 cards inside a row using javascript?

Card looks like this

<div class="card" style="width: 18rem;">
  <img src=${thumbnail} class="card-img-top" alt="...">
  <div class="card-body">
    <h5 class="card-title">${scriptName}</h5>
    <p class="card-text">${description}</p>
    <a href=${link} class="btn btn-primary">Go somewhere</a>
  </div>
</div>

This here is my Javascript file

async function getScript(){
    const scripts = await fetch('./scripts.json')
    const response = await scripts.json()
    //console.log(response[0])
    const scripta = response[0]['scripts']['web3py']
    const image = response[0]['scripts']['web3py'][0]['thumbnail']
   
    const title = response[0]['scripts']['web3py'][0]['scriptName']
    const description = response[0]['scripts']['web3py'][0]['description']
    console.log(title)


    let content = '';

scripta.forEach(p => {
  content += `
    <div id="keyBoard" class="col-md-4 mt-2">
              <div class="card" style="width: 18rem;">
                  <img src="${image}" class="card-img-top img-fluid" alt="keyboard">
                  <div class="card-body">
                      <h5 class="card-title" id="itemName">${title}</h5>
                      <p class="card-text" id="itemDesc">${description}</p>
                      <p class="card-text"></p>
                      <a href="#" class="btn btn-primary" id="addCart">Add to cart</a>
                  </div>
              </div>
          </div>
  `
});

document.querySelector("#shop").innerHTML = content;
    

}
getScript()

the problem is that this function prints out the 1st item 4 times in 1 row instead of the 1 item each in 1 row

1 Answers

You can loop over the JSON data using a nested loop and then use an empty variable to build the HTML string. Then insert that HTML using insertAdjacentHTML. Additional comments within the code breaking down what each line is doing.

const main = document.getElementById('main')
// an empty variable to hold the card as it is built within a for loop
const jsonObj = [{
  "scripts": {
    "web3py": [{
        "thumbnail": "images/thumbnails/sendetherweb3py.png",
        "scriptName": "send Native",
        "description": "send native with web3py",
        "link": "https://jsonformatter.org/img/tom-cruise.jpg"
      },
      {
        "thumbnail": "images/thumbnails/sendtokenweb3py.png",
        "scriptName": "send token",
        "description": "send erc20 token with web3py",
        "link": "https://jsonformatter.org/img/tom-cruise.jpg"
      },
      {
        "thumbnail": "images/thumbnails/swapnativeweb3py.png",
        "scriptName": "swap native token dex",
        "description": "swap eth for erc20 token",
        "link": "https://jsonformatter.org/img/tom-cruise.jpg"
      },
      {
        "thumbnail": "images/thumbnails/swaptokenweb3py.png",
        "scriptName": "swap erc20 token on dex",
        "description": "swap erc20 token with erc20 token",
        "link": "https://jsonformatter.org/img/tom-cruise.jpg"
      }
    ],
    "web3js": [{
        "thumbnail": "images/thumbnails/swaptokenethers.png",
        "scriptName": "swap token on dex",
        "description": "swap erc20 token with token on a dex",
        "link": "https://jsonformatter.org/img/tom-cruise.jpg"
      },
      {
        "thumbnail": "images/thumbnails/swapnativeethers.png",
        "scriptName": "swap native",
        "description": "swap native for token on dex",
        "link": "https://jsonformatter.org/img/tom-cruise.jpg"
      },
      {
        "thumbnail": "images/thumbnails/sendtokenethers.png",
        "scriptName": "send ERC20 token",
        "description": "send erc20 token with ethers",
        "link": "https://jsonformatter.org/img/tom-cruise.jpg"
      },
      {
        "thumbnail": "images/thumbnails/sendnativeethers.png",
        "scriptName": "send native",
        "description": "send Native ETH with ethers",
        "link": "https://jsonformatter.org/img/tom-cruise.jpg"
      }
    ]
  }
}]

// define the object
const scripts = jsonObj[0]['scripts']
// define an output variable to hold HTML
let output = ''
// loop over the two nested arrays
for (let objs in scripts) {
  // set first row
  output += '<div class="d-flex">'
  // get data from first array of objects
  scripts[objs].forEach(item => {  
     output += `
     <div class="card ${objs}" style="width: 18rem;">
      <img src=${item["thumbnail"]} class="card-img-top col-sm flex-row" alt="...">
      <div class="card-body col-sm">
        <h5 class="card-title">${item["scriptName"]}</h5>
        <p class="card-text">${item["description"]}</p>
        <a href=${item["link"]} class="btn btn-primary">Go somewhere</a>
      </div>
    </div>`
  })
  // close the row
  output += '</div>'
}

// insert the HTML using .insertAdjacentHTML
main.insertAdjacentHTML('afterbegin', output)
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8" crossorigin="anonymous"></script>
<div id="main"></div>

Related