Search code examples
javascriptforeach

How to retrieve user input and show user input card Javascript?


Trying to filter user input so when user starts to type run function.

What I want

When the user starts to type, start looking for cards when the class product-name and display block results.

ex:

user starts typing something... Piz

display block card Pizza

My Javascript

// search bar function
const search = () => {
    var input, filter, data, productName, i, txtValue;
    data = this.data;
    input = document.getElementById("user-input");
    filter = input.value.toUpperCase();
    getInput = input.value;
    console.log("User input: " + getInput);
    
    document.querySelectorAll('.cards').forEach(function(data) {
        for (i = 0; i < data.length; i++) {
            productName = data[i].querySelectorAll(".produce-name")[0];
            txtValue = productName.textContent || productName.innerText;
            if (txtValue.toUpperCase().indexOf(filter) > -1) {
                data[i].style.display = "";
            } else {
                data[i].style.display = "none";
            }
        }
     });
};

My HTML

<form class="form-inline flexSearchWrapper">
  <input class="form-control mr-sm-2" type="search" placeholder="Busca algo..." aria-label="Search" id="user-input" onkeyup="search();">
</form>

I can't figure out what I'm doing wrong? At the moment my console.log() output just gets the user input and what they are currently typing.Thanks!

UPDATE

Card Info HTML

<div class="card cards">
  <img src="https://images.vexels.com/media/users/3/185266/isolated/lists/815ded7afc1c54dfb5a60f81f68f928b-pizza-slice-icon.png" class="card-img-top p-3 product-image" alt="...">
  <div class="card-body">
    <h5 class="card-title product-name">Pizza</h5>
    <h5 class="text-muted fw-bold card-price product-price">S/ 12.50 PEN</h5>
  </div>
</div>

I put it in a .forEach loop in order to get the .product-name of each card.


Solution

  • Your solution isn't working because of a couple of issues:

    1. You have a nested loop inside of forEach. data is a single card element. Looping through it will loop through it's properties, which is not what you need.
    2. The product name is in the .product-name class, not the .produce-name. Also be sure to use querySelector instead of querySelectorAll if you need a single element.

    Below I've written a different version of your code. Instead of looking up the title element of each card, add the data you need to the .card element itself. You can do this with data attributes. In this case I've added data-name to each card, which is going to be the value which we can filter on.

    Then when you input something in the search field, get the value of the field and loop over all the cards. If the data-name value contains anything that you've entered, then a class will be added or removed to show or hide the card. By using classes you can keep CSS in charge of the styles.

    const form = document.querySelector('#search');
    const cards = document.querySelectorAll('.card')
    
    form.addEventListener('input', event => {
      const value = event.target.value.trim().toLowerCase();
      
      for (const card of cards) {
        const { name } = card.dataset;
        const shouldShow = name.includes(value);
        card.classList.toggle('hide', !shouldShow);
      }
    });
    .cards {
      display: flex;
      gap: 10px;
    }
    
    .card.hide {
      display: none;
    }
    <form id="search" class="form-inline flexSearchWrapper">
      <input class="form-control mr-sm-2" type="search" placeholder="Busca algo..." aria-label="Search" id="user-input">
    </form>
    
    <div class="cards">
      <div class="card" data-name="pizza">
        <img src="https://images.vexels.com/media/users/3/185266/isolated/lists/815ded7afc1c54dfb5a60f81f68f928b-pizza-slice-icon.png" class="card-img-top p-3 product-image" alt="...">
        
        <div class="card-body">
          <h5 class="card-title product-name"><a href="#" class="test">Pizza</h5>
          <p class="text-muted fw-bold card-price product-price">S/ 12.50 PEN</p>
        </div>
      </div>
      
      <div class="card" data-name="penne">
        <img src="https://images.vexels.com/media/users/3/185266/isolated/lists/815ded7afc1c54dfb5a60f81f68f928b-pizza-slice-icon.png" class="card-img-top p-3 product-image" alt="...">
        
        <div class="card-body">
          <h5 class="card-title product-name"><a href="#" class="test">Penne</h5>
          <p class="text-muted fw-bold card-price product-price">S/ 12.50 PEN</p>
        </div>
      </div>
    </div>

    I've also used the cards class differently as it doesn't make sense - at least for me - for a single card to have both card and cards as a class.

    And be sure to use your headings h1...h6 properly. It's not for styling but to explain to the browser how it should interpret the content.