My goal is filter data based on a user's selection in a drop-down menu.
SET UP
I have an array of objects named employees
. First, I sort by the salary
attribute, then using another function manipulateData()
, I filter by role
attribute (which the user selects via a drop-down menu).
(notice in the HTML file that the manipulateData()
function is called onchange
)
Here is my code:
JavaScript:
let employees = [
{
id : 1,
name : 'John Smith',
role : 'Sales',
salary : 100000
},
{
id : 2,
name : 'Mary Jones',
role : 'Finance',
salary : 78000,
},
{
id : 3,
name : 'Philip Lee',
role : 'Finance',
salary : 160000,
},
{
id : 4,
name : 'Susan Williams',
role : 'Sales',
salary : 225000,
},
{
id : 5,
name : 'Jason Alexander',
role : 'Finance',
salary : 90000,
},
{
id : 6,
name : 'Derek Sanders',
role : 'Sales',
salary : 140000,
}
]
// #########################################
function filterData() {
let allData = employees;
let selectBox = document.getElementById("employee-role");
let selectedValue = selectBox.options[selectBox.selectedIndex].value;
// SORT SALARIES DESCENDING
allData.sort(function (a, b) {
return b.salary - a.salary;
})
console.log('Sorted Data', allData);
// *** Here is where I'd like to invoke the dataManipulation() function to filter on only the user-selected roles
// LIMIT TO ONLY 2 RECORDS
let filteredData = allData.filter( (value, index) => {
return (index < 2);
});
// RENDER THE CHART
//renderChart(filteredData);
}
function manipulateData(filteredData) {
return filteredData.filter(e => e.role === selectedValue)
}
HTML:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="description" content="">
<title>Example</title>
</head>
<body>
<div >
<!-- header -->
<div >
<div >
<h1>Example</h1>
</div>
</div>
<!-- drop down menu -->
<div >
<div >
<div >
<div >
<select id="employee-role" onchange="manipulateData()">
<option value="All">All Roles</option>
<option value="Sales">Sales</option>
<option value="Finance">Finance</option>
</select>
</div>
</div>
</div>
</div>
<!-- container of bar chart -->
<div id="chart-area"></div>
</div>
</body>
</html>
Question: before I reduce the size of the data set to 2 records, how would I incorporate the manipulateData()
function to grab only the role
selected by the user via the drop-down menu?
Thanks! (JavaScript newbie here)
CodePudding user response:
You can call manipulateData(allData, selectedValue)
directly with your data set. After this, you can remove onchange="manipulateData()"
in your HTML.
let employees = [{
id: 1,
name: 'John Smith',
role: 'Sales',
salary: 100000
},
{
id: 2,
name: 'Mary Jones',
role: 'Finance',
salary: 78000,
},
{
id: 3,
name: 'Philip Lee',
role: 'Finance',
salary: 160000,
},
{
id: 4,
name: 'Susan Williams',
role: 'Sales',
salary: 225000,
},
{
id: 5,
name: 'Jason Alexander',
role: 'Finance',
salary: 90000,
},
{
id: 6,
name: 'Derek Sanders',
role: 'Sales',
salary: 140000,
}
]
function filterData() {
let allData = employees;
let selectBox = document.getElementById("employee-role");
let selectedValue = selectBox.options[selectBox.selectedIndex].value;
// SORT SALARIES DESCENDING
allData.sort(function(a, b) {
return b.salary - a.salary;
})
//call `manipulateData` and pass `allData` to the param for filtering
let filteredData = manipulateData(allData, selectedValue)
// LIMIT TO ONLY 2 RECORDS
filteredData = filteredData.filter((value, index) => {
return (index < 2);
});
console.log(filteredData)
// RENDER THE CHART
//renderChart(filteredData);
}
function manipulateData(filteredData, selectedValue) {
if(selectedValue === "All") {
return //skip this logic, if the value is `All`
}
return filteredData.filter(e => e.role === selectedValue)
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="description" content="">
<title>Example</title>
</head>
<body>
<div >
<!-- header -->
<div >
<div >
<h1>Example</h1>
</div>
</div>
<!-- drop down menu -->
<div >
<div >
<div >
<div >
<select id="employee-role" >
<option value="All">All Roles</option>
<option value="Sales">Sales</option>
<option value="Finance">Finance</option>
</select>
</div>
</div>
</div>
</div>
<button onclick="filterData()">
Check filtered data
</button>
<!-- container of bar chart -->
<div id="chart-area"></div>
</div>
</body>
</html>
Note that I added Check filtered data
for the demo purpose. You can remove it and fill in other elements at your needs.
CodePudding user response:
You want to modify the results down to the top two earners after the data is filtered.
filteredByRole.slice(0, 2);
Details are commented in example
const employees = [{
id: 1,
name: 'John Smith',
role: 'Sales',
salary: 100000
}, {
id: 2,
name: 'Mary Jones',
role: 'Finance',
salary: 78000
}, {
id: 3,
name: 'Philip Lee',
role: 'Finance',
salary: 160000
}, {
id: 4,
name: 'Susan Williams',
role: 'Sales',
salary: 225000
}, {
id: 5,
name: 'Jason Alexander',
role: 'Finance',
salary: 90000
}, {
id: 6,
name: 'Derek Sanders',
role: 'Sales',
salary: 140000
}];
const data = employees.sort((a, b) => b.salary - a.salary);
// Declare empty array outside of function
let filteredByRole = [];
// Register the <select> to the "change" event
document.getElementById("employee-role").onchange = filterRole;
// Event handler passes event object by default
function filterRole(event) {
// Assign the current value of <select> to a variable
const role = this.value;
/*
If <select> current value is "All" then the array is the same...
...otherwise, filter each object (employee) and return only the properties
that has a value that matches the current value of <select>
*/
if (role === "All") {
filteredByRole = data.slice(0);
} else {
filteredByRole = data.filter(employee => employee.role === role);
}
// Log the filtered data
console.log("Filtered by Role: ");
console.log(JSON.stringify(filteredByRole));
console.log("|||||||||||||||||||||||||||||");
// Log the data for the top 2 earners
console.log("Top two Earners by Role: ");
console.log(JSON.stringify(filteredByRole.slice(0, 2)));
console.log("|||||||||||||||||||||||||||||");
}
<select id="employee-role" >
<option value="All">All Roles</option>
<option value="Sales">Sales</option>
<option value="Finance">Finance</option>
</select>