I am trying to select a group of radio buttons on a page. Each of the inputs have the following:
<input type="radio" class="wc-pao-addon-field wc-pao-addon-radio" name="addon-761-soapbar-covers-0[]" data-raw-price="32" data-price="32" data-price-type="quantity_based" value="gold-soapbar-set" data-label="Gold Soapbar (Set)">
I can’t select by the data attributes as they are shared with other inputs that I don’t want to disable. So far, I can only grab the value as the value changes from gold to raw-nickel to polished-nickel to chrome, etc.
What I have is the following:
//Initialize empty array
this.metalCovers = [];
//Grab all inputs
this.covers = Array.from(this.soapbarCovers.querySelectorAll("input"));
//Then filter them by their values and store in new variable
this.chromeCovers = this.covers.filter((cover) => cover.value.indexOf("chrome") !== -1);
this.blackCovers = this.covers.filter((cover) => cover.value.indexOf("matte") !== -1);
this.goldCovers = this.covers.filter((cover) => cover.value.indexOf("gold") !== -1);
this.nickelCovers = this.covers.filter((cover) => cover.value.indexOf("nickel") !== -1);
//Create new array from filtered inputs
this.metalCovers = [this.chromeCovers, this.blackCovers, this.goldCovers, this.nickelCovers];
//flatten the new array
this.metalCovers = [].concat.apply([], this.metalCovers);
So, this works, but I’m trying to discover a cleaner way to approach this code. I was thinking it would clean it up if I could Array.filter() by multiple values, but nothing came up in my research.
Does anything stick out to you?
>Solution :
I’d just do something like
// Define the keywords we're looking for in the value
const keywords = ["chrome", "matte", "gold", "nickel"];
// Grab all inputs
const inputs = Array.from(this.soapbarCovers.querySelectorAll("input"));
// Filter them...
this.metalCovers = inputs.filter((cover) =>
// If any of the keywords appears in the value,
// this is an input we care about
keywords.some((kw) => cover.value.includes(kw))
);
Or if you want to be really efficient and have the browser CSS engine do all the work,
this.metalCovers = Array.from(this.soapbarCovers.querySelectorAll("input[value*=chrome],input[value*=matte],input[value*=gold],input[value*=nickel]"));
which of course can be made more maintainable via
const keywords = ["chrome", "matte", "gold", "nickel"];
this.metalCovers = Array.from(this.soapbarCovers.querySelectorAll(keywords.map(k => `input[value*=${k}`]).join(','));