skip to Main Content

I have a search.js file that reads a json file and retrieves information about some products, and then displays it in the page.
I am trying to show a error message if no product is found when searching, and this part is almost working.
If a search for a non-existent product, the error message appears correctly:
enter image description here

The problem is, if I search for a product that the name isn’t similar to another one, the error still appears.. for example:
enter image description here

enter image description here

Json file structure is like this:

[
    {
        "nome": "Carro",
        "apelido": "ft.car",
        "desc": "descrição",
        "img": "/img/carro.png",
        "link": "/pag/carro.html"
    }, 
    {
        "nome": "Carreta Bi-Trem",
        "apelido": "ft.big.truck",
        "desc": "descrição",
        "img": "/img/carreta.png",
        "link": "/pag/carreta.html"
    }
...
]

HTML of the error div:

        <div class="col-12 d-none" id="avisoDeErro">
          <div class="alert alert-danger p-5 rounded shadow">
            <i class="bi bi-x-circle-fill"></i> <strong>Erro</strong>
            <hr>
            <div class="fs-1 ">
              Nenhum produto encontrado.
              <p class="fw-light">Acha que deveria ter algo aqui? Entre em contato com o suporte.</p>
            </div>
          </div>
        </div>

search.js file:

const produtosCardTemplate = document.querySelector("[data-produtos-template]");
const produtosCardContainer = document.querySelector("[data-produtos-cards-container]");
const searchInput = document.querySelector("[data-search]");

let produtos = [];

searchInput.addEventListener("input", (e) => {
    const value = e.target.value.toLowerCase()
    produtos.forEach(produto => {
        console.log(value)
        const isVisible = value.split(' ').every(word => produto.nome.toLowerCase().includes(word)) || value.split('.').every(word => produto.apelido.toLowerCase().includes(word))
        produto.element.classList.toggle("hide", !isVisible) //hide = display: none !important; 
        console.log(isVisible)
        
        // Show a error message
        if (!isVisible){
            let avisoErro = document.getElementById("avisoDeErro")
            avisoErro.classList.remove('d-none')
        } else {
            let avisoErro = document.getElementById("avisoDeErro")
            avisoErro.classList.add('d-none');
        }
    })
})

fetch("/produtos.json")
    .then(res => res.json())
    .then(data => {
        produtos = data.map(produto => {
            // console.log(produto)

            const card = produtosCardTemplate.content.cloneNode(true).children[0]
            const nome = card.querySelector("[data-nome]")
            const desc = card.querySelector("[data-desc]")
            const img = card.querySelector("[data-img]")
            const imgLink = card.querySelector("[data-img-link]")
            const link = card.querySelector("[data-link]")
            
            nome.textContent = produto.nome
            desc.textContent = produto.desc
            img.setAttribute("src", produto.img)
            imgLink.setAttribute("href", produto.link) 
            link.setAttribute("href", produto.link)

            produtosCardContainer.append(card)

            return {nome: produto.nome, apelido: produto.apelido, element: card}
        });
    });

I know that the problem is in my way of showing the error message

        if (!isVisible){
            let avisoErro = document.getElementById("avisoDeErro")
            avisoErro.classList.remove('d-none')
        } else {
            let avisoErro = document.getElementById("avisoDeErro")
            avisoErro.classList.add('d-none');
        }

But i can’t think of another way of doing this

Tried changing the way to see if no product matched, with no success

2

Answers


  1. Chosen as BEST ANSWER

    Using the logic provided by Yash Maheshwari above, i was able to solve my problem with this:

    searchInput.addEventListener("input", (e) => {
    const value = e.target.value.toLowerCase()
    let algumProdutoCorresponde = false;
    
    produtos.forEach(produto => {
        console.log(value)
        const isVisible = value.split(' ').every(word => produto.nome.toLowerCase().includes(word)) || value.split('.').every(word => produto.apelido.toLowerCase().includes(word))
        produto.element.classList.toggle("hide", !isVisible)
    
        if (isVisible) {
            algumProdutoCorresponde = true;
        }
    })
    let avisoErro = document.getElementById("avisoDeErro");
    avisoErro.classList.toggle('d-none', algumProdutoCorresponde);
    

    })


  2. As you have added the logic to display the error message inside the forEach loop, and as the loop runs for each product, if any of the products from the list does not match the search value, then an error message will be displayed, and also the matched products will be displayed.

    searchInput.addEventListener("input", (e) => {
      let avisoErro = document.getElementById("avisoDeErro")
      const value = e.target.value.toLowerCase()
    
      const matchedProducts = produtos.filter(produto => {
        if(value.split(' ').every(word => produto.nome.toLowerCase().includes(word)) || value.split('.').every(word => produto.apelido.toLowerCase().includes(word))) {
          produto.element.classList.toggle("hide", !isVisible) //hide = display: none !important;
          return true;  
        }
      })
    
      const isVisible = matchedProducts.length <= 0
      // Show an error message only when none of the product matched
      if (!isVisible){
        avisoErro.classList.remove('d-none')
      } else {
        avisoErro.classList.add('d-none');
      }
    })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search