简体   繁体   中英

Sorting an array of objects by property using eventlisteners with a dropdown list

So I'm creating a view that shows a list of ads. Each ad is an object in an array and has properties (title, description, dates, etc.) I wrote the javascript to display them in order and created a drop down list of title, description, date, etc. and need to sort the ads according to the selected property in the drop down list. I have a function that sorts the objects by property, and I want to have eventlisteners on each option selected, but then I'm not sure how to implement this since I'm using a loop to display all the ad objects.

<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
    <div id="sortList">

      <select id="selectSort" onchange="myFunction()">
        <option value="value1">value1
        <option value="value2">value2
        <option value="value3">value3
      </select>
    </div>
    <div id="container"></div>
  </body>
</html>

Script

var array = [
    {
        value1: "this is an attribute", value2: "this is the second attribute", value3: "this is the 3rd attribute"


    },
    {
        value1: "this is an attribute of 2nd object", value2: "this is the second attribute of 2nd object", value3: "this is the 3rd attribute of 2nd object"
    },
    {
        value1: "this is an attribute of 2nd object", value2: "this is the second attribute of 2nd object", value3: "this is the 3rd attribute of 2nd object"
    },
];


   const container = document.getElementById("container"); 

  for( { value1, value2, value3 } of array) {


    const wrapper =  document.createElement("div");
    wrapper.className = "wrapper";
    const first= document.createElement("h1");
    first.textContent = value1;
    const second= document.createElement("p");
    second.textContent = value2;    
    const third= document.createElement("sub");
    third.textContent = value3;


   // append 
    wrapper.appendChild(first);
    wrapper.appendChild(second);
    wrapper.appendChild(third);
    container.appendChild(wrapper);

 }

//function that sorts ads by properties 

function sortBy(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a,b) {
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

//I want to have eventlisteners on each option selected but then not sure how to implement this since I'm using a loop to display all the ads

array.sort(sortBy("value1"));

You can try like this way to add an eventlistener on your select element and then grab the selected value on your myFunction() . But before that you've modify your option values first, like this to easily get and use it on your sorting function.

<select id="selectSort" onchange="myFunction(this.value)">
    <option value="title">Title</option>
    <option value="description">Description</option>
    <option value="start_date">Start date</option>
    <option value="end_date">End date</option>
    <option value="offer">Most products</option>
    <option value="num_of_products">Least products</option>
</select>

Also initialize the content of container.innerHTML = ''; it'll help you to refresh your div after changing the sort order. I've also wrap it bodyContent() function for the code re-usability. Hope this helps :) See your pen here again

 var ads = [{ title: "Photo Play Paper Collections", description: "Don't miss these brand new Photo Play Paper Collections!", start_date: "2018-09-01", end_date: "2018-12-30", offer: "50% Off", num_of_products: 7 }, { title: "Foil & Foiling Accessories", description: "Once you add this color & shine to your paper, wood, fabric, or other porous surfaces you'll want to do it over and over again.", start_date: "2018-08-01", end_date: "2018-11-30", offer: "Save $25", num_of_products: 10 }, { title: "The Halloween Shop", description: "Shop all our spooky supplies in one place!", start_date: "2018-09-01", end_date: "2018-10-30", offer: "35% Off", num_of_products: 8 }, { title: "Waffle Flower Crafts Stamps & Dies", description: "We can't stop talking about these new Waffle Flower Stamps and Dies!", start_date: "2018-09-01", end_date: "2018-09-30", offer: "Save $30", num_of_products: 19 }, { title: "Die Cutting & Embossing", description: "Save on Die Cutting and Embossing Folders at Blitsy! Shop hundreds of amazing Dies and Embossing Folders from brilliant designers at Sizzix, Spellbinders, and CottageCutz (to name a few!)", start_date: "2018-08-01", end_date: "2018-12-30", offer: "Save $50", num_of_products: 23 }, { title: "American Crafts Tools, Paper Collections & More", description: "American Crafts prides themselves on innovation with their scrapbooking products. You can find crafting embellishments, stickers, and more.", start_date: "2018-08-01", end_date: "2018-11-30", offer: "45% Off", num_of_products: 35 }, { title: "The Fall Shop!", description: "The Fall Shop has everything you need for the upcoming season!", start_date: "2018-09-01", end_date: "2018-09-30", offer: "60% Off", num_of_products: 50 }, { title: "Moxy Glitter, Embossing Powers, & More!", description: "Eye catching glitters from this new brand by American Crafts!", start_date: "2018-09-01", end_date: "2018-09-30", offer: "10% Off", num_of_products: 24 }, { title: "Brutus Monroe Stamps, Dies, Tools & More", description: "On Sale Now! New Arrivals from Brutus Monroe", start_date: "2018-08-01", end_date: "2018-10-30", offer: "Save $75", num_of_products: 10 }, { title: "Fiskars Tools & Accessories", description: "Shop All the New Tools & Accessories that will make your life easier.", start_date: "2018-08-01", end_date: "2018-09-30", offer: "15% Off", num_of_products: 5 }, ]; function bodyContent() { const container = document.getElementById("container"); container.innerHTML = ''; for ({ title, description, start_date, end_date, offer, num_of_products } of ads) { const wrapper = document.createElement("div"); wrapper.className = "wrapper"; const headline = document.createElement("h1"); headline.textContent = title; const descrip = document.createElement("p"); descrip.textContent = description; const dates = document.createElement("sub"); dates.textContent = "Offer valid " + start_date + " through " + end_date; const discount = document.createElement("h2"); discount.textContent = offer; const products = document.createElement("h4"); products.innerHTML = num_of_products + " items still available! <a href=#>Shop Now</a>"; // append wrapper.appendChild(headline); wrapper.appendChild(discount); wrapper.appendChild(descrip); wrapper.appendChild(products); wrapper.appendChild(dates); container.appendChild(wrapper); } } bodyContent() //function that sorts ads by properties function sortBy(property) { var sortOrder = 1; if (property[0] === "-") { sortOrder = -1; property = property.substr(1); } return function(a, b) { var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0; return result * sortOrder; } } //I want to have eventlisteners on each option selected but then not sure how to implement this since I'm using a loop to display all the ads function myFunction(value) { ads.sort(sortBy(value)); bodyContent() } 
 body { font-family: Arial, Helvetica, sans-serif; } div { margin: 5%; } .wrapper { border: 2px solid #3abac4; padding:5%; } h4 a { text-decoration: none; color: #fff; background-color: #3abac4; margin: 10px; padding: 10px; } h4 a:hover { color: #3abac4; background-color: #fff; border: 2px solid #3abac4; } 
 <!DOCTYPE html> <html> <head> </head> <body> <div id="sortList"> <select id="selectSort" onchange="myFunction(this.value)"> <option value="title">Title</option> <option value="description">Description</option> <option value="start_date">Start date</option> <option value="end_date">End date</option> <option value="offer">Most products</option> <option value="num_of_products">Least products</option> </select> </div> <div id="container"></div> </body> </html> 

I'll only ask to the Question's title (EDIT: you've edited the title). The DOM stuff is easy (and frankly I didn't work with it for last few years).

To sort by property:

ads.sort((a, b) => a[selectedProp] > b[selectedProp] ? 1 : -1)

Then you should somehow update your view (don't know how to do it, I am spoiled with frameworks like angular, react etc.), probably using React or Vue.js. Doing a loop is good. You just loop the same array. The only thing you need is to update the view.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM