简体   繁体   中英

How to add multiple cards by clicking on the search result

My current script allows you to add a card + some info about its content by clicking on the result of a search bar.

The objective is to create a sort of movies list. However, I do not know how, where or if I should implement a loop to add multiple cards, instead of replacing one.

My biggest issue is that after clicking on the result item, the active card is replaced by the new one.

The first function loads the content based on an API. It basically clears the search bar after clicking on the item shown through the research. It also calls the function responsible for adding a div (a card with the movie informations) to the HTML.

function loadContentDetails(){
const searchListContent = searchList.querySelectorAll('.search-list-item');

searchListContent.forEach(content => {
    content.addEventListener('click', async () =>{
        searchList.classList.add('hide-search-list');
        searchBar.value = "";
        const result = await fetch(`http://www.omdbapi.com/?i=${content.dataset.id}&apikey=60ee3e91`);
        const contentDetails = await result.json();
        displayContentDetails(contentDetails);
    });
});}

The second function creates a new card based on what the user selected through the search bar.

function displayContentDetails(details){
cardsGroupFlex.innerHTML = `
    <div class="card">
        <img src="${(details.Poster != "N/A") ? details.Poster: "resources/img-not-found.png"}" alt="" class="card-img" />
        <div class="card-description">
            <p class="card-title">${details.Title}</p>
            <p> ${(details.Plot)} </p>
        </div>
    </div>
    `;
}

I would much appreciate your help.

Change cardsGroupFlex.innerHTML = to cardsGroupFlex.innerHTML += (add a "+" sign before the "="). This will concatenate a new card to the innerHTML rather than replacing the innerHTML with the new card:

cardsGroupFlex.innerHTML += `
    <div class="card">
        <img src="${(details.Poster != "N/A") ? details.Poster: "resources/img-not-found.png"}" alt="" class="card-img" />
        <div class="card-description">
            <p class="card-title">${details.Title}</p>
            <p> ${(details.Plot)} </p>
        </div>
    </div>
    `;

A simple solution is to instead of setting the innerHTML of cardsGroupFlex , you could append the card to the end of the innerHTML .

// instead of
cardsGroupFlex.innerHTML = `...`
// appending with +=
cardsGroupFlex.innerHTML += `...`

However if you're going to implement a feature like deleting or editing the cards, you're going to need to have a global array of the card's details, and looping over all of them inside displayContentDetails .

This solution could also make use of appending to the end of a string.

function displayContentDetails(){

  let newInner = ''

  for (const details of globalCards) {
    inner += `
    <div class="card">
        <img src="${(details.Poster != "N/A") ? details.Poster: "resources/img-not-found.png"}" alt="" class="card-img" />
        <div class="card-description">
            <p class="card-title">${details.Title}</p>
            <p> ${(details.Plot)} </p>
        </div>
    </div>
    `
  }
}

One quick note: don't use searchList.classList.add as a function/method. It's a property. So do as following to add classes.

searchList.classList.add = 'hide-search-list';

This is just from a quick observation on your code.

You are overriding the innerHTML instead of appending to it. You can append it, see snippet 1

 let cardsGroupFlex = document.getElementById("cardsGroupFlex"); function displayContentDetails(details){ cardsGroupFlex.innerHTML += ` <div class="card"> <img src="${(details.Poster != "N/A") ? details.Poster: "resources/img-not-found.png"}" alt="" class="card-img" /> <div class="card-description"> <p class="card-title">${details.Title}</p> <p> ${(details.Plot)} </p> </div> </div> `; } let detailArray = [ { Poster: "Poster1", Title: "Title1", Plot: "Plot1" }, { Poster: "Poster2", Title: "Title2", Plot: "Plot2" }, { Poster: "Poster2", Title: "Title2", Plot: "Plot2" }, ]; for (let d of detailArray) displayContentDetails(d);
 <div id="cardsGroupFlex"></div>

Yet, it is not very healthy to always append to innerHTML from the perspective of performance, so let's improve the code above by generating the structure first and only then set the innerHTML :

 let cardsGroupFlex = document.getElementById("cardsGroupFlex"); function getContentDetails(details){ return ` <div class="card"> <img src="${(details.Poster != "N/A") ? details.Poster: "resources/img-not-found.png"}" alt="" class="card-img" /> <div class="card-description"> <p class="card-title">${details.Title}</p> <p> ${(details.Plot)} </p> </div> </div> `; } let detailArray = [ { Poster: "Poster1", Title: "Title1", Plot: "Plot1" }, { Poster: "Poster2", Title: "Title2", Plot: "Plot2" }, { Poster: "Poster2", Title: "Title2", Plot: "Plot2" }, ]; cardsGroupFlex.innerHTML = detailArray.map(item => getContentDetails(item)).join("");
 <div id="cardsGroupFlex"></div>

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