Nothing shows in my console from a filtered object

114 Views Asked by At

I am building a simple mattress shop for my school. I need to filter by price range and firmness. I have the items object hardcoded and need them to be filtered. I am just trying to get it logged so I can then display them or hide them.

$(document).ready(function() {
  $(".dropdown-trigger").dropdown().on("change", handleDropdownChange);
});

function handleDropdownChange(event) {
  const selectedOption = $(event.target).val();

  let filteredItems;

  if (selectedOption === "Soft") {
    filteredItems = Object.keys(items).filter(key => items[key].firmness === "soft");
  } else if (selectedOption === "Firm") {
    filteredItems = Object.keys(items).filter(key => items[key].firmness === "firm");
  } else if (selectedOption === "Price: Lowest-Highest") {
    filteredItems = Object.keys(items).sort((a, b) => items[a].price - items[b].price);
  } else if (selectedOption === "Price: Highest-Lowest") {
    filteredItems = Object.keys(items).sort((a, b) => items[b].price - items[a].price);
  } else {
    filteredItems = Object.keys(items);
  }

  console.log(filteredItems);
  // Use the filteredItems array to display the filtered items
  // displayFilteredItems(filteredItems);
}

var items = {
    "large-model-a1132v32023": {
      "title": "Nectar Premier King Size",
      "price": 1199.00,
      "image": "./assets/images/KingSizeEX1.jpg",
      "firmness": "medium"
    },
    "large-model-a1132v32024": {
      "title": "Helix Moonlight Luxe",
      "price": 2155.30,
      "image": "./assets/images/KingProduct2.jpg",
      "firmness": "soft"
    },
    "large-model-a1132v32025": {
      "title": "Purple Restore™ Hybrid Mattress",
      "price": 2595.00,
      "image": "./assets/images/KingProduct3.jpg",
      "firmness": "firm"
    },
    "queen-model-a1132v32024": {
      "title": "Brooklyn Bedding Signature Hybrid",
      "price": 1299.99,
      "image": "Queenphoto1 - instasize",
      "firmness": "soft"
    },
    "queen-model-a1132v32025": {
      "title": "The WinkBed",
      "price": 1499.99,
      "image": "queenphoto2 - instasize",
      "firmness": "firm"
    },
    "queen-model-a1132v32026": {
      "title": "Layla Hybrid Mattress",
      "price": 1699.99,
      "image": "assets/images/Queenphoto3 - instasize.webp",
      "firmness": "soft"
    },
    "twin-model-a1132v32024": {
      "title": "Bestselling T&N Mint Mattress",
      "price": 1095.00,
      "image": "add",
      "firmness": "medium"
    },
    "twin-model-a1132v32025": {
      "title": "Saatva Youth Mattress",
      "price": 795.00,
      "image": "add",
      "firmness": "medium"
    },
    "twin-model-a1132v32026": {
      "title": "Helix Sunset",
      "price": 936.30,
      "image": "add",
      "firmness": "soft"
    },
    "full-model-a1132v32024": {
      "title": "The Allswell",
      "price": 227.00,
      "image": "add",
      "firmness": "medium"
    },
    "full-model-a1132v32025": {
      "title": "Nectar Premier Copper 14",
      "price": 999.99,
      "image": "add",
      "firmness": "medium"
    },
    "full-model-a1132v32026": {
      "title": "Casper Element",
      "price": 506.00,
      "image": "add",
      "firmness": "medium"
    }
  };
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<ul id="dropdown1" class="dropdown-content">
    <li><a href="#!">Soft</a></li>
    <li class="divider"></li>
    <li><a href="#!">Firm</a></li>
    <li class="divider"></li>
    <li><a href="#!">Price: Lowest-Highest</a></li>
    <li class="divider"></li>
    <li><a href="#!">Price: Highest-Lowest</a></li>
</ul>

<!--Nav links left side-->
<ul id="nav-mobile" class="left hide-on-med-and-down">
    <li><a href="#kingSize">King Size</a></li>
    <li><a href="#queenSize">Queen Size</a></li>
    <li><a href="#twinSize">Twin Size</a></li>
    <li><a href="#fullSize">Full Size</a></li>
    <li><a href="#Aboutus">About us</a></li>
    <li><a class="dropdown-trigger" href="#!" data-target="dropdown1">Sort by</a></li>
</ul>

I've tried multiple things like changing to all jquery and also including the object within the function. I'm still new any help? I am using Materialize CSS and have to for the specifications of the grade. https://materializecss.com/navbar.html I used their docs for the .dropdown() function and my navbar wont activate the dropdown without it. Thanks.

3

There are 3 best solutions below

3
ingoCollatz On BEST ANSWER

I never used jquery or materialize css but I'm pretty sure jquerys on("event", xyz) function is not usable on the metrializecss-dropdown()-function, as it does not bypass the event that jquerys eventlistener can handle.

I have built a solution, where the dropwon-function and your handleDropdownChange are being called seperatly on its own elements.

Your filter-options (Soft, Firm, Price: Lowest-Highest, Price: Highest-Lowest) now have an own class filterTrigger.

<ul id="dropdown1" class="dropdown-content">
  <li><a href="#!" class="filterTrigger">Soft</a></li>
  <li class="divider"></li>
  <li><a href="#!" class="filterTrigger">Firm</a></li>
  <li class="divider"></li>
  <li><a href="#!" class="filterTrigger">Price: Lowest-Highest</a></li>
  <li class="divider"></li>
  <li><a href="#!" class="filterTrigger">Price: Highest-Lowest</a></li>
</ul>

Each filterTrigger gets an eventListener on which your handleDropdownChange is being called. Note I didn't use .val() as it seems to return nothing useful for the comparison. I used .text() instead.

$(document).ready(function () {
  $(".dropdown-trigger").dropdown();
  $(".filterTrigger").each(function () {
    $(this).on("click", function () {
      handleDropdownChange($(this).text());
    });
  });
});

Regarding your filterlogic: On that way you will only get an array of the items title (e.g. ['large-model-a1132v32025', 'queen-model-a1132v32025'])

If you need an array of each object containing the data (firmness, price etc.) you can use the filter and sort function on Object.fromEntries(Object.entries(items).filter()/.sort())

https://masteringjs.io/tutorials/fundamentals/filter-key

  if (selectedOption === "Soft") {
    filteredItems = Object.fromEntries(
      Object.entries(items).filter(
        ([key, value]) => value.firmness === "soft"
      )
    );
  } else if (selectedOption === "Firm") {
    filteredItems = Object.fromEntries(
      Object.entries(items).filter(
        ([key, value]) => value.firmness === "firm"
      )
    );
  } else if (selectedOption === "Price: Lowest-Highest") {
    filteredItems = Object.fromEntries(
      Object.entries(items).sort(([, a], [, b]) => a.price - b.price)
    );
  } else if (selectedOption === "Price: Highest-Lowest") {
    filteredItems = Object.fromEntries(
      Object.entries(items).sort(([, a], [, b]) => b.price - a.price)
    );
  } else {
    filteredItems = Object.keys(items);
  }

Edit: This only provides a solution for filter or sort.

i have added a solution for filter and sort in the second snipped

Checkout the code-snipped.

Note in your handleDropdownChange function, you can pass the parameter directly into the comparisons. It doesn't need to be stored in an extra variable.

filter or sort

$(document).ready(function () {
  $(".dropdown-trigger").dropdown();
  $(".filterTrigger").each(function () {
    $(this).on("click", function () {
      handleDropdownChange($(this).text());
    });
  });
});


function handleDropdownChange(selectedOption) {    
  let filteredItems;


  if (selectedOption === "Soft") {
    filteredItems = Object.fromEntries(
      Object.entries(items).filter(
        ([key, value]) => value.firmness === "soft"
      )
    );
  } else if (selectedOption === "Firm") {
    filteredItems = Object.fromEntries(
      Object.entries(items).filter(
        ([key, value]) => value.firmness === "firm"
      )
    );
  } else if (selectedOption === "Price: Lowest-Highest") {
    filteredItems = Object.fromEntries(
      Object.entries(items).sort(([, a], [, b]) => a.price - b.price)
    );
  } else if (selectedOption === "Price: Highest-Lowest") {
    filteredItems = Object.fromEntries(
      Object.entries(items).sort(([, a], [, b]) => b.price - a.price)
    );
  } else {
    filteredItems = Object.keys(items);
  }

  console.log(filteredItems);
  // Use the filteredItems array to display the filtered items
  // displayFilteredItems(filteredItems);
}

var items = {
  "large-model-a1132v32023": {
    title: "Nectar Premier King Size",
    price: 1199.0,
    image: "./assets/images/KingSizeEX1.jpg",
    firmness: "medium",
  },
  "large-model-a1132v32024": {
    title: "Helix Moonlight Luxe",
    price: 2155.3,
    image: "./assets/images/KingProduct2.jpg",
    firmness: "soft",
  },
  "large-model-a1132v32025": {
    title: "Purple Restore™ Hybrid Mattress",
    price: 2595.0,
    image: "./assets/images/KingProduct3.jpg",
    firmness: "firm",
  },
  "queen-model-a1132v32024": {
    title: "Brooklyn Bedding Signature Hybrid",
    price: 1299.99,
    image: "Queenphoto1 - instasize",
    firmness: "soft",
  },
  "queen-model-a1132v32025": {
    title: "The WinkBed",
    price: 1499.99,
    image: "queenphoto2 - instasize",
    firmness: "firm",
  },
  "queen-model-a1132v32026": {
    title: "Layla Hybrid Mattress",
    price: 1699.99,
    image: "assets/images/Queenphoto3 - instasize.webp",
    firmness: "soft",
  },
  "twin-model-a1132v32024": {
    title: "Bestselling T&N Mint Mattress",
    price: 1095.0,
    image: "add",
    firmness: "medium",
  },
  "twin-model-a1132v32025": {
    title: "Saatva Youth Mattress",
    price: 795.0,
    image: "add",
    firmness: "medium",
  },
  "twin-model-a1132v32026": {
    title: "Helix Sunset",
    price: 936.3,
    image: "add",
    firmness: "soft",
  },
  "full-model-a1132v32024": {
    title: "The Allswell",
    price: 227.0,
    image: "add",
    firmness: "medium",
  },
  "full-model-a1132v32025": {
    title: "Nectar Premier Copper 14",
    price: 999.99,
    image: "add",
    firmness: "medium",
  },
  "full-model-a1132v32026": {
    title: "Casper Element",
    price: 506.0,
    image: "add",
    firmness: "medium",
  },
};
  

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css"
    />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
  </head>
  <body>
    <ul id="dropdown1" class="dropdown-content">
      <li><a href="#!" class="filterTrigger">Soft</a></li>
      <li class="divider"></li>
      <li><a href="#!" class="filterTrigger">Firm</a></li>
      <li class="divider"></li>
      <li><a href="#!" class="filterTrigger">Price: Lowest-Highest</a></li>
      <li class="divider"></li>
      <li><a href="#!" class="filterTrigger">Price: Highest-Lowest</a></li>
    </ul>

    <!--Nav links left side-->
    <ul id="nav-mobile" class="left hide-on-med-and-down">
      <li><a href="#kingSize">King Size</a></li>
      <li><a href="#queenSize">Queen Size</a></li>
      <li><a href="#twinSize">Twin Size</a></li>
      <li><a href="#fullSize">Full Size</a></li>
      <li><a href="#Aboutus">About us</a></li>
      <li>
        <a class="dropdown-trigger" href="#!" data-target="dropdown1"
          >Sort by</a
        >
      </li>
    </ul>
  </body>
</html>

Filter and sort

$(document).ready(function () {
      $(".dropdown-trigger").dropdown();
      $(".filterTrigger").each(function () {
        $(this).on("click", function () {
          filterItemsByFirmness($(this).text());
        });
      });
      $(".sortTrigger").each(function () {
        $(this).on("click", function () {
          sortItemsByPrice(items, filteredItems, $(this).text());
        });
      });
    });

    let filteredItems;

    function sortItemsByPrice(items, filteredItems, option) {
      let _items = filteredItems;
      if (filteredItems === undefined) {
        _items = items;
      }

      let sortedItems;
      if (option === "Price: Lowest-Highest") {
        sortedItems = Object.fromEntries(
          Object.entries(_items).sort(([, a], [, b]) => a.price - b.price)
        );
      }
      if (option === "Price: Highest-Lowest") {
        sortedItems = Object.fromEntries(
          Object.entries(_items).sort(([, a], [, b]) => b.price - a.price)
        );
      }
      console.log("sortedItems", sortedItems);
    }

    function filterItemsByFirmness(selectedOption) {
      if (selectedOption === "Soft") {
        filteredItems = Object.fromEntries(
          Object.entries(items).filter(
            ([key, value]) => value.firmness === "soft"
          )
        );
      } else if (selectedOption === "Firm") {
        filteredItems = Object.fromEntries(
          Object.entries(items).filter(
            ([key, value]) => value.firmness === "firm"
          )
        );
      } else {
        filteredItems = Object.keys(items);
      }

      console.log(filteredItems);
      // Use the filteredItems array to display the filtered items
      // displayFilteredItems(filteredItems);
    }

    var items = {
      "large-model-a1132v32023": {
        title: "Nectar Premier King Size",
        price: 1199.0,
        image: "./assets/images/KingSizeEX1.jpg",
        firmness: "medium",
      },
      "large-model-a1132v32024": {
        title: "Helix Moonlight Luxe",
        price: 2155.3,
        image: "./assets/images/KingProduct2.jpg",
        firmness: "soft",
      },
      "large-model-a1132v32025": {
        title: "Purple Restore™ Hybrid Mattress",
        price: 2595.0,
        image: "./assets/images/KingProduct3.jpg",
        firmness: "firm",
      },
      "queen-model-a1132v32024": {
        title: "Brooklyn Bedding Signature Hybrid",
        price: 1299.99,
        image: "Queenphoto1 - instasize",
        firmness: "soft",
      },
      "queen-model-a1132v32025": {
        title: "The WinkBed",
        price: 1499.99,
        image: "queenphoto2 - instasize",
        firmness: "firm",
      },
      "queen-model-a1132v32026": {
        title: "Layla Hybrid Mattress",
        price: 1699.99,
        image: "assets/images/Queenphoto3 - instasize.webp",
        firmness: "soft",
      },
      "twin-model-a1132v32024": {
        title: "Bestselling T&N Mint Mattress",
        price: 1095.0,
        image: "add",
        firmness: "medium",
      },
      "twin-model-a1132v32025": {
        title: "Saatva Youth Mattress",
        price: 795.0,
        image: "add",
        firmness: "medium",
      },
      "twin-model-a1132v32026": {
        title: "Helix Sunset",
        price: 936.3,
        image: "add",
        firmness: "soft",
      },
      "full-model-a1132v32024": {
        title: "The Allswell",
        price: 227.0,
        image: "add",
        firmness: "medium",
      },
      "full-model-a1132v32025": {
        title: "Nectar Premier Copper 14",
        price: 999.99,
        image: "add",
        firmness: "medium",
      },
      "full-model-a1132v32026": {
        title: "Casper Element",
        price: 506.0,
        image: "add",
        firmness: "medium",
      },
    };
  

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css"
    />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
  </head>
  <body>
    <ul id="dropdown1" class="dropdown-content">
      <li><a href="#!" class="filterTrigger">Soft</a></li>
      <li class="divider"></li>
      <li><a href="#!" class="filterTrigger">Firm</a></li>
      <li class="divider"></li>
      <li><a href="#!" class="sortTrigger">Price: Lowest-Highest</a></li>
      <li class="divider"></li>
      <li><a href="#!" class="sortTrigger">Price: Highest-Lowest</a></li>
    </ul>

    <!--Nav links left side-->
    <ul id="nav-mobile" class="left hide-on-med-and-down">
      <li><a href="#kingSize">King Size</a></li>
      <li><a href="#queenSize">Queen Size</a></li>
      <li><a href="#twinSize">Twin Size</a></li>
      <li><a href="#fullSize">Full Size</a></li>
      <li><a href="#Aboutus">About us</a></li>
      <li>
        <a class="dropdown-trigger" href="#!" data-target="dropdown1"
          >Sort by</a
        >
      </li>
    </ul>
  </body>
    </html>

1
马博学 On
<ul id="nav-mobile" class="left hide-on-med-and-down">
<li class="opt isShow"><a href="#kingSize">King Size</a></li>
<li class="opt isShow"><a href="#queenSize">Queen Size</a></li>
<li class="opt isShow"><a href="#twinSize">Twin Size</a></li>
<li class="opt isShow"><a href="#fullSize">Full Size</a></li>
<li class="opt isShow"><a href="#Aboutus">About us</a></li>
<li><a class="dropdown-trigger" href="#!" data-target="dropdown1">Sort by</a></li></ul>


// css part
.isShow {
    display: none;
  }




// JS Part
$(document).ready(function () {
  // click .dropdown-trigger element, switch .opt(li element) hide or display 
  $(".dropdown-trigger").on("click", () => {
    $('.opt').toggleClass('isShow')
  });

  $('.opt').on('click', handleDropdownChange)
});

function handleDropdownChange(event) {
  const selectedOption = $(event.target).val();

  let filteredItems;

  if (selectedOption === "Soft") {
    filteredItems = Object.keys(items).filter(key => items[key].firmness === "soft");
  } else if (selectedOption === "Firm") {
    filteredItems = Object.keys(items).filter(key => items[key].firmness === "firm");
  } else if (selectedOption === "Price: Lowest-Highest") {
    filteredItems = Object.keys(items).sort((a, b) => items[a].price - items[b].price);
  } else if (selectedOption === "Price: Highest-Lowest") {
    filteredItems = Object.keys(items).sort((a, b) => items[b].price - items[a].price);
  } else {
    filteredItems = Object.keys(items);
  }

  console.log(filteredItems);
3
Carsten Massmann On

Your snippet seems not to be complete. The <ul> and <li> elements need to be turned into some kind of select elements. I have chosen to replace them with simple HTML <select> elements and concentrated on the filtering issue of your question.

I also turned your initial items object into an array. Arrays are easier to filter and map into HTML, as I have demonstrated below.

My snippet filters the itmes elements according to (max.) two criteria. Everything happens in the handleDropdownChange function:

var items = Object.entries({"large-model-a1132v32023": {"title": "Nectar Premier King Size","price": 1199.00,"image": "./assets/images/KingSizeEX1.jpg","firmness": "medium"},"large-model-a1132v32024": {"title": "Helix Moonlight Luxe","price": 2155.30,"image": "./assets/images/KingProduct2.jpg","firmness": "soft"},"large-model-a1132v32025": {"title": "Purple Restore™ Hybrid Mattress","price": 2595.00,"image": "./assets/images/KingProduct3.jpg","firmness": "firm"},"queen-model-a1132v32024": {"title": "Brooklyn Bedding Signature Hybrid","price": 1299.99,"image": "Queenphoto1 - instasize","firmness": "soft"},"queen-model-a1132v32025": {"title": "The WinkBed","price": 1499.99,"image": "queenphoto2 - instasize","firmness": "firm"},"queen-model-a1132v32026": {"title": "Layla Hybrid Mattress","price": 1699.99,"image": "assets/images/Queenphoto3 - instasize.webp","firmness": "soft"},"twin-model-a1132v32024": {"title": "Bestselling T&N Mint Mattress","price": 1095.00,"image": "add","firmness": "medium"},"twin-model-a1132v32025": {"title": "Saatva Youth Mattress","price": 795.00,"image": "add","firmness": "medium"},"twin-model-a1132v32026": {"title": "Helix Sunset","price": 936.30,"image": "add","firmness": "soft"},"full-model-a1132v32024": {"title": "The Allswell","price": 227.00,"image": "add","firmness": "medium"},"full-model-a1132v32025": {"title": "Nectar Premier Copper 14","price": 999.99,"image": "add","firmness": "medium"},"full-model-a1132v32026": {"title": "Casper Element","price": 506.00,"image": "add","firmness": "medium"}})
  .map(([k,v,size,id])=>( // turn the object into an array of objects
  [size,id]=k.split("-model-"), {size, id, ...v} ));

$(document).ready(function() {
  function handleDropdownChange(ev){
    if (this.tagName=="BUTTON") { // toggle sort direction
      var txt=this.textContent=this.textContent.split(" ").reverse().join(" "),
       sign=txt[0]=="h"?1:-1; // get current sort direction ...
    }
    const [firm,size]=sels.map((i,sel)=>sel.value).toArray();
    $("#show").html(
     items.filter(itm=>itm.size.includes(size) && itm.firmness.includes(firm))
          .sort((a,b)=>sign*(b.price-a.price))
          .map(tableRow).join("\n")
    );
  }
  const sels=$("select.filt").on("change", handleDropdownChange),
        btn=$("#sortbtn").on("click",handleDropdownChange).click()

});

function tableRow(itm){
 return `<tr id="${itm.id}"><td>${itm.title}</td><td>${itm.size}</td><td>${itm.firmness}</td><td>${itm.price.toFixed(2)} $</td><td>${itm.image}</td></tr>`;
}
td:nth-child(4){text-align:right}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<select id="dropdown1" class="filt dropdown-content">
    <option value="soft">Soft</option>
    <option value="medium">Medium</option>
    <option value="firm">Firm</option>
    <option value="" selected>all</option>
</select>

<!--Nav links left side-->
<select id="nav-mobile" class="filt left hide-on-med-and-down">
    <option value="large">King Size</option>
    <option value="queen">Queen Size</option>
    <option value="twin">Twin Size</option>
    <option value="full">Full Size</option>
    <option value="" selected>all sizes</option>
</select> sort by price:
<button id="sortbtn">highest to lowest</button>

<table>
<thead>
<tr><th>title</th><th>size</th><th>firmness</th><th>price</th><th>image</th></tr>
</thead>
<tbody id="show"></tbody>
</table>

The sorting is now defined by another button (#sortbtn). Clicking on it will change the sort direction.