Reputation: 53
I am trying to output data with the .filter() method in javascript and I can't figuer out if its possible to make it work how I want. First here is the code :
function filterMenu(e) {
const category = e.target.dataset.id;
if (category === "all") {
getData()
.then((res) => {
displayMenuItems(res);
})
.catch((err) => console.log(err));
} else {
getData()
.then(function (res) {
res.filter(function (menuItem) {
if (menuItem.category === category) {
let output = [];
output = `
<article class="menu-item">
<img src="${menuItem.img}" alt="${menuItem.title}" class="photo" />
<div class="item-info">
<header>
<h4>${menuItem.title}</h4>
<h4 class="price">${menuItem.price}</h4>
</header>
<p class="item-text">${menuItem.desc}</p>
</div>
</article>
`;
populateMenu.innerHTML = output;
console.log(output);
}
});
})
.catch((err) => console.log(err));
}
}
So we have 4 buttons, 3 of which are categories and 1 is a all button so after we press the all button everything works as intended and that is the if statement, however when we get to the else statement by clicking the category button it only display's the last element in the output variable of the category that is clicked, but when I run the console.log(output) it shows :
<article class="menu-item">
<img src="./images/item-1.jpeg" alt="buttermilk pancakes" class="photo" />
<div class="item-info">
<header>
<h4>buttermilk pancakes</h4>
<h4 class="price">15.99</h4>
</header>
<p class="item-text">I'm baby woke mlkshk wolf bitters live-edge blue bottle, hammock freegan copper mug whatever cold-pressed </p>
</div>
</article>
<article class="menu-item">
<img src="./images/item-4.jpeg" alt="country delight" class="photo" />
<div class="item-info">
<header>
<h4>country delight</h4>
<h4 class="price">20.99</h4>
</header>
<p class="item-text">Shabby chic keffiyeh neutra snackwave pork belly shoreditch. Prism austin mlkshk truffaut, </p>
</div>
</article>
<article class="menu-item">
<img src="./images/item-7.jpeg" alt="bacon overflow" class="photo" />
<div class="item-info">
<header>
<h4>bacon overflow</h4>
<h4 class="price">8.99</h4>
</header>
<p class="item-text">carry jianbing normcore freegan. Viral single-origin coffee live-edge, pork belly cloud bread iceland put a bird </p>
</div>
</article>
Now I can use the populateMenu.innerHTML += output and it works but it does not work as intented, if we use the += then every single time a category button is clicked the data is inserted over and over again and I don't want that, everything works as intented atm, when the button is clicked the right data is inserted in the page but for the category it just display's the last element and I've been trying to figuer out I still don't know what's wrong or if its possible to make it work how I want.
Upvotes: 3
Views: 111
Reputation: 823
I intuit from your code that displayMenuItems() populates populateMenu.innerHTML, and I believe that you want all filtered items to populate the menu. So, I have refactored the code as follows:
function filterMenu(e) {
const category = e.target.dataset.id;
let finalResult = [];
getData()
.then((res) => {
if (category === "all") {
finalResult = res;
} else {
finalResult = res.filter((menuItem) => menuItem.category === category);
}
displayMenuItems(finalResult);
})
.catch((err) => console.log(err));
}
We are simply calling displayMenuItems() with either the result or the filtered result, as appropriate.
Note that filter() returns a new array, so the code is certain to capture the return value in finalResult.
Upvotes: 1
Reputation: 1285
Array filter returns the list of all items which pass a condition.
If you want only the first match, try <array>.find
.
In your case, it should be
var matchedItem = res.find(function (menuItem) {
return menuItem.category === category;
})
if(matchedItem){
output = `
<article class="menu-item">
<img src="${matchedItem.img}" alt="${matchedItem.title}" class="photo" />
<div class="item-info">
<header>
<h4>${matchedItem.title}</h4>
<h4 class="price">${matchedItem.price}</h4>
</header>
<p class="item-text">${matchedItem.desc}</p>
</div>
</article>
`;
}
Upvotes: 1