Home > Back-end >  JavaScript: using onchange to filter data using a drop-down menu
JavaScript: using onchange to filter data using a drop-down menu

Time:09-13

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>

  • Related