javascript - array filtering does not work as expected -
i have array of objects , wanna filter them based on size, color , collar.
everything works expected whenever uncheck checkbox when re-check again brings unwanted objects.
var database = [ {id:0o1, size: "xl", color:"red", collar: "v-neck"}, {id:0o2, size: "s", color:"blue", collar: "regular"}, {id:0o3, size: "xxl", color:"red", collar: "scoop"}, {id:0o4, size: "l", color:"green", collar: "v-neck"}, {id:0o5, size: "xl", color:"blue", collar: "turtle-neck"}, {id:0o6, size: "l", color:"red", collar: "v-neck"} ]; window.onload = function () { var vneckcollarcheckbox = document.queryselector('#vneck-collar-checkbox'); var xlsizecheckbox = document.queryselector('#xl-size-checkbox'); var redcolorcheckbox = document.queryselector('#red-color-checkbox'); var div = document.queryselector('div'); var db = database; function filterbyvneckcollar() { let vneckcollar = database.filter(function (item) { return item.collar === "v-neck"; }); if(!vneckcollarcheckbox.checked){ db = db.filter(function (i) { return vneckcollar.indexof(i) < 0; }); div.innerhtml = json.stringify(db); } else{ db = db.concat(vneckcollar); div.innerhtml = json.stringify(db); } } function filterbyxlsize() { let xlsize = database.filter(function (item) { return item.size === "xl"; }); if(!xlsizecheckbox.checked){ db = db.filter(function (i) { return xlsize.indexof(i) < 0; }); div.innerhtml = json.stringify(db); } else{ db = db.concat(xlsize); div.innerhtml = json.stringify(db); } } function filterbyredcolor() { let redcolor = database.filter(function (item) { return item.color === "red"; }); if(!redcolorcheckbox.checked){ db = db.filter(function (i) { return redcolor.indexof(i) < 0; }); div.innerhtml = json.stringify(db); } else{ db = db.concat(redcolor); div.innerhtml = json.stringify(db); } } div.innerhtml = json.stringify(db); vneckcollarcheckbox.addeventlistener('change', filterbyvneckcollar); xlsizecheckbox.addeventlistener('change', filterbyxlsize); redcolorcheckbox.addeventlistener('change', filterbyredcolor); };
<html> <head> <script src="js.js"></script> </head> <body> <form action="#"> <input type="checkbox" id="vneck-collar-checkbox" checked> <label for="vneck-collar-checkbox">v-neck collar</label> <br> <input type="checkbox" id="xl-size-checkbox" checked> <label for="xl-size-checkbox">xl size</label> <br> <input type="checkbox" id="red-color-checkbox" checked> <label for="red-color-checkbox">red color</label> </form> <div></div> </body> </html>
try this:
- uncheck "red color"
- uncheck "xl size"
- check "xl size"
you see object containing "color: red" appears.
i know problem in db = db.concat(xxxxx); of else{} statement don't know how achieve desired output.
any other solution/concept achieve sort of filter appreciated.
just filter on database
once combination of rules need.
i've put jsdoc on more complicated function you, made generic can used other things too
/** * @callback filterruletest * @param {object} obj target object * @returns {boolean} whether obj passed test */ /** * @typedef {object} filterrule * @property {string} [key] property key find on target * @property {string} [value] value assigned key of target * @property {filterruletest} [test] function run on target, return bool */ /** filters array of objects * @param {[object]} arrayofobjects array of objects filter * @param {[filterrule]} arrayofrules array of objects filter * @param {boolean} [invert] return opposite of rules * @param {boolean} [emptyrulepasses] default behaviour of empty rule * @returns {[object]} filtered result */ function objfilter(arrayofobjects, arrayofrules, invert = false, emptyrulepasses = false) { return arrayofobjects.filter(obj => { return invert !== arrayofrules.every(rule => { if ('key' in rule) { if ('value' in rule) return obj[rule.key] === obj[rule.value]; return rule.key in obj; } if ('test' in rule) { return rule.test(obj); } return emptyrulepasses; }); }); } function createfilterrules(collar, size, color) { let rules = []; if (collar) rules.push({key: 'collar', value: collar}); if (size) rules.push({key: 'size', value: size}); if (color) rules.push({key: 'color', value: color}); return rules; } const vneckcollarcheckbox = document.queryselector('#vneck-collar-checkbox'); const xlsizecheckbox = document.queryselector('#xl-size-checkbox'); const redcolorcheckbox = document.queryselector('#red-color-checkbox'); const div = document.queryselector('div'); function filterclothes(db) { return objfilter( db, createfilterrules( vneckcollarcheckbox.checked ? 'v-neck' : null, xlsizecheckbox.checked ? 'xl' : null, redcolorcheckbox.checked ? 'red' : null ) ); } function clotheshandle() { div.innerhtml = json.stringify(filterclothes(database)); } vneckcollarcheckbox.addeventlistener('change', clotheshandle); xlsizecheckbox.addeventlistener('change', clotheshandle); redcolorcheckbox.addeventlistener('change', clotheshandle);
Comments
Post a Comment