Currently, I'm building a search application that searches/filters stores(Custom Post Type) based on the store-feature(Custom Taxamonies) IDs. Originally, I tried to filter the data using a query string, but I could not find a way to receive an exact match since you cannot use && within a query string.
Store Features examples:
Pop - ID 12
car wash - ID 22
Deli - ID 36
Beer - ID 54
ATM - ID 98
Stores:
Store One store-features: 54, 98, 22
Store Two store-features: 54, 55, 36
Store Three store-features: 98, 55, 12
Example of what I'm looking for: Only show a store the contains both ids of 54 and 98 (store one). Unfortunately, since I can't use && in a query string it will then return an array of all three stores in the object. Note: I have around 50 stores and 30 different store features.
I figured the best path forward is to iterate through the returned stores and compare the requested store-feature ids with all the store-feature ids for each individual store. The problem is, the only way I've found so far to check if all store-feature id exists is by using the .includes() method. In theory, it works, but I can't use it since I won't know which store features the user will be looking for.
let storeFeatureID = [array of the store features]
Promise.all([
fetchData(`http://localhost/wordpress/wp-json/wp/v2/locations/?store-features=${storeFeatureID}`),
// "data" in this instance would return three stores since all three stores have either the id of 54 and 98.
]).then((data) => {
const locationData = data[0];
allLocations(locationData);
});
const allLocations = (data) => {
// empty object and array
let storeData = {}, storeArray = [];
// loops through the object
for (let i = 0; i < data.length; i ) {
let myStoresID = data[i]["store-features"];
// checks to see if the store feature ID is within the array. If so, push the store into an empty array(Store Array) and then push it into the empty object (Store Data)
// need a better way to filter this
if ( myStoresID.includes(54) && myStoresID.includes(98)){
console.log('fordata', data[i]);
storeData = data[i];
storeArray.push(storeData);
}
}
let location = storeArray;
let html = "";
let locationAmmount;
//calls sorting fuction
location.sort(dynamicSort("slug"));
for (let j = 0; j < location.length; j ) {
html = `<li><a href="${location[j].link}">${location[j].title.rendered}</a></li>`;
locationAmmount = j;
}
if (locationAmmount >= 0) {
locationAmmount = 1;
document.getElementById("location-container").innerHTML = html;
document.getElementById("feature-results").innerHTML = `<h2>Results: ${locationAmmount}</h2>`;
}
else {
document.getElementById("location-container").innerHTML =
"<h2>Sorry, no results</h2>";
document.getElementById("feature-results").innerHTML = `<h2>Results: 0</h2>`;
}
};
CodePudding user response:
The combination of Array.prototype.filter()
, Array.prototype.every()
and Array.prototype.includes()
will get you there:
const data=[[
{name:"Store One", "store-features":[54, 98, 22]},
{name:"Store Two","store-features":[54, 55, 36]},
{name:"Store Three","store-features":[98, 55, 12]}
]];
let features=[54,22]; // array of required features (can be any length)
console.log(data[0].filter(st=>features.every(f => st["store-features"].includes(f) ) ) );
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
If location
is an actual JavaScript Array, you can use filter(...)
var subarray = location.filter(function(storeID) {
return storeID.includes(54) && storeID.includes(98);
});
If for instance your storeIDs are coming from checkboxes, you can do something like
var subarray = location.filter(function(storeID) {
const filterIDs = document.querySelectorAll("input[checkbox]:checked");
for (var i = 0; i < filterIDs.length) {
if (!storeID.includes(fillterIDs[i].value)) return false;
}
return true;
});