简体   繁体   中英

How to print/render nested objects properties using html in javaScript file

I am searching on nested objects. I want to render objects properties but every time i have to go in object like mobiles.apple.iphone12.properties. I have multiple mobiles in object if i do like that it will be very lengthy code. I just want to print in shorter way. Check out the JavaScript code below.

 let searchBtn = document.getElementById('search-btn') let mobiles = { apple: { iphone13: { model: 'iphone 13', color: 'black', price: 1000, camera: 20, battery: 500, }, iphone12: { model: 'iphone 12', color: 'red', price: 800, camera: 15, battery: 400, src: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRhdp92UKK3NxwNfcIBlyZX8g26kEYBG3WNoQ&usqp=CAU" } }, samsung: { s10: { model: 'Samsung S10', color: 'black', price: 500, camera: 10, battery: 600, }, a10: { model: 'Samsung A10 ', color: 'blue', price: 300, camera: 20, battery: 150, } }, moto: { motoz: { model: 'Moto Z', color: 'black', price: 500, camera: 10, battery: 300, }, motoe4: { model: 'Moto E4', color: 'black', price: 200, camera: 10, battery: 300, } }, techno: { camon18: { model: 'Camon 18', color: 'golden', price: 5000, camera: 10, battery: 300, }, spark7: { model: 'Spark 7', color: 'sky blue', price: 2000, camera: 10, battery: 300, } } } searchBtn.addEventListener('click', function () { let brandName = document.getElementById('brand-name').value let modelName = document.getElementById('model-name').value if (mobiles[brandName] !== undefined) { if (mobiles[brandName][modelName] !== undefined) { console.log(mobiles[brandName][modelName]) } else { console.log('This model is not available') } } else if (brandName == '' || modelName == '') { console.log('Brand name OR Model name is empty') } else { console.log('This model is not available') } }) let card = `<div class="card"> <img src="${mobiles.apple.iphone12.src}" style="width:100%"> <h1> ${mobiles.apple.iphone12.model} </h1> <p class="price"> Rs: ${mobiles.apple.iphone12.price}</p> <p> Color: ${mobiles.apple.iphone12.color} </p> <p> Battery: ${mobiles.apple.iphone12.battery} </p> <p><button>Add to Cart</button></p> </div>` document.getElementById("container").innerHTML += card
 #container { display: flex; justify-content: space-around; flex-wrap: wrap; } .card { box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); width: 300px; margin: 50px; text-align: center; font-family: arial; } img { margin-top: 20px; } .price { color: grey; font-size: 22px; } .card button { border: none; padding: 12px; color: white; background-color: #000; text-align: center; cursor: pointer; width: 100%; font-size: 18px; } .card button:active { opacity: 0.7; }
 <input type="text" id="brand-name" placeholder="Enter Brand Name"> <input type="text" id="model-name" placeholder="Enter Model Name"> <button id="search-btn">Searh Phone</button> <div id="container"> </div>

So from my understanding you are trying to create the initial displayed items.

You can have a generic function that generates the cards filtered or unfiltered.

const generateCards = (brand = '', model = '') => {
    const fragment = document.createDocumentFragment();
    
    Object.entries(mobiles)
    .filter(([key]) => key.includes(brand))
    .forEach(([, mobile]) => {
        Object.entries(mobile)
        .filter(([key]) => key.includes(model))
        .forEach(([, model])=> {
            const card = document.createElement('div');
            card.classList.add('card');
            card.innerHTML = `${model.src ? ('<img src=' + model.src + '} style="width:100%">') : ''}
                <h1> ${model.model} </h1>
                <p class="price"> Rs: ${model.price}</p>
                <p> Color: ${model.color} </p>
                <p> Battery: ${model.battery} </p>
                <p><button>Add to Cart</button></p>`;
            fragment.appendChild(card)
        })
    })

    document.getElementById("container").innerHTML = fragment;
}

Then you can call generateCards() initially and it will generate all of the cards, and on the listeners for the brand and model you just call it with those values generateCards(brand, model)

I'm assuming, reading your question, that you want a user to search for a brand/model and get as output the device specs (if present).

If so, first thing you should do is to put the creation of the card inside your eventlistener definition, otherwise you won't be able to render any of them.

I made some changes in the snippet below; in this case you don't have to create card specifying model and brand in advance.

 searchBtn.addEventListener('click', function () { let brandName = document.getElementById('brand-name').value; let modelName = document.getElementById('model-name').value; if (!mobiles[brandName] || brandName == '') { console.log('Brand not available'); return; } if (!mobiles[brandName][modelName] || modelName == '') { console.log('Model not available'); return; } console.log(mobiles[brandName][modelName]); // Clear previous search document.getElementById('container').innerHTML = null; document.getElementById('container').innerHTML += getMobileinfoHtmlElement( mobiles[brandName][modelName] ); }); function getMobileinfoHtmlElement(mobile) { return `<div class="card"> <img src="${mobile.src}" style="width:100%"> <h1> ${mobile.model} </h1> <p class="price"> Rs: ${mobile.price}</p> <p> Color: ${mobile.color} </p> <p> Battery: ${mobile.battery} </p> <p><button>Add to Cart</button></p> </div>`; }

This code works if you are going to use nested objects. Speaking about best practice, arrays should be better; they have pre-built methods like .filter() or .find() that can be useful in this case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM