Array: Sortera array med många alternativ
Jag har en html hemsida som har många checkboxes. Dom ska filtrera en array som sedan ska visas när man trycker på en html knapp.
Min Array:
var ImgList = [
{ImgName:"img1",ImgLink:"#", Funny:false, Animals:true},
{ImgName:"img2",ImgLink:"#", Funny:true, Animals:false},
{ImgName:"img3",ImgLink:"#", Funny:true, Animals:false}
];
Jag har försökt med:
const nyLista= ImgList.filter(obj => obj.FunnyImg === true);
console.log(nylista);
Men då har jag använt en checkbox och eftersom jag vill ha flera checkboxes som ska filtrera listan mer än en gång och med olika values för varje checkbox.
Så hur filtrerar jag listan på bästa sätt?
Ska FunnyImg i ditt förslag vara Funny, som det står i koden övanför?
Man får hitta ett booleskt uttryck för när det ska matcha, givet objektet och checkboxen. Om vi kallar tillhörande checkbox-värde för checkfunny (som man har plockat fram med findObject("FunnyBox").nånting, jag kan inte det här utantill) så vill vi att objektet ska väljas när både funnybox och obj.Funny är sanna, och vi vill också alltid ha med det om funnybox är falsk, för då ska vi inte välja bort något, om jag har förstått uppgiften rätt.
Det booleska uttrycket blir:
obj.Funny || !funnybox
(nu har jag tagit bort jämförelsen === true, för det borde inte behövas med booleska värden). Man kan se logiken som att ett objekt ska filtreras bort precis närcheckboxen är ikryssad men objektet inte har den egenskapen.
Koden för dina båda egenskaper kan bli så här:
const nyLista= ImgList.filter(obj => (obj.Funny || !funnybox) && (obj.Animals || !animalsbox));
Man kan också loopa över alla checkboxar som finns och filtrera på en i taget.
Om man har ett stort antal checkboxar så kan man vilja gå igenom dem i en loop i stället för att namnge dem en och en.
Rubriken säger "sortera" (ändra ordning på element), men vad jag kan förstå handlar problemet om att "filtrera" (ta bort element)...
Jag har ändrat från var till let jämfört med ditt exempel, då var är ett gammalmodig sätt att deklarera variabler i JavaScript, jag har ändrat till att inte inleda egenskaper med stor bokstav (normalt inleder man bara klassnamn med stora bokstäver i JavaScript), jag tog bort "Img" i dina egenskapsnamn, samt ändrade från "name" till "src"...
Här är en lösning som automatiskt skapar checkboxes för alla image-egenskaper som är booleaner (just nu funny och animals) och gör en filtrering.
Lösningen använder sig mycket av olik arraymetoder för att filtrera (filter, every), men också för att omvandla datan till html (map, join). Den använder sig även av template literals (flerradiga strängar med insprängda uttryck).
// En lista av bilder
let imgList = [
{ src: "img1.jpg", link: "#", funny: false, animals: true },
{ src: "img2.jpg", link: "#", funny: true, animals: false },
{ src: "img3.jpg", link: "#", funny: true, animals: true }
];// Returnera egenskaper som filtrering ska ske på
// (alla booleanska egenskaper i imgList)
const propsToFilterBy = () => Object.entries(imgList[0]).filter(
([key, val]) => typeof val === 'boolean'
).map(([key]) => key);// Skapa html för checkboxar
// (en checkbox per booleansk egenskap i en image)
const createCheckBoxes = () => `
<form id="filters">
Only show images that are/contains:<br/>
${propsToFilterBy().map(x => `
${x} <input type="checkbox" name="${x}">
`).join('')}
</form>
`;// Skapa en filtrerad imgList
// (läs värden på checkboxar och filtrera utifrån dem)
const filteredImgList = () => imgList.filter(img =>
propsToFilterBy().every(
prop => img[prop] || !document.forms.filters[prop].checked)
);// Skapa html för filteredImgList
const createImgList = (list) => `
<div id="imageList">
${list.map(img => `
<a href="${img.link}"><img src="${img.src}"${img.src}></a>
`).join('')}
</div>
`;// Visa checkboxes och lista av bilder
const div = document.createElement('div');
div.innerHTML = createCheckBoxes() + createImgList(imgList);
document.body.append(div);// Lägg till eventhanterare för klick på checkboxar
// (som triggar en omrendering av den filtrerade listan)
// Notera: Delegerad eventhantering
document.body.addEventListener('click', e => {
if (!e.target.closest('#filters [type="checkbox"]')) { return; }
document.querySelector('#imageList').innerHTML =
createImgList(filteredImgList());
});