Search code examples
javascriptjqueryjavascript-objects

How to filter object array based on attribute of data-type?


I have the following JavaScript array of people objects that is being rendered dynamically from JS. What I would like to do is be able to perform a filter on the objects being rendered based on what is selected in the dropdown menu option and what that value matches with the attribute data-type that collects the department property value from each object.

Is there something I only need to change in the if/else condition, because that is where I'm getting stuck. Everything else is working fine. I'm unable to link the input value with the objects kay value, department.

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
    <title>People Directory</title>
</head>
<body>
    <h1 class="page-title">Directory</h1>
    <div>
        <label for="department-type">Department</label>
        <select name="department" id="department-type">
            <option value="" disabled selected>-Any-</option>
            <option value="dean of the office">Dean of the Office</option>
            <option value="admissions">Admissions</option>
            <option value="faculty">Faculty</option>
        </select>
    </div>
    <div class="directory-container"></div>
</body>
</html>

JavaScript

const peoples = [{
    name: 'Victor McGee',
    job: 'Dean of School',
    department: 'Dean of the office'
},
{
    name: 'Joe Pong',
    job: 'Academics',
    department: 'Admissions'
},
{
    name: 'Amy Baxter',
    job: 'Professor',
    department: 'Faculty'
}];

// console.log(peoples);

const renderDirectory = function(peoples) {

    peoples.forEach(function(people) {
        // create card element/wrapper
        const card = document.createElement('div');
        card.classList = 'card-body'
        card.setAttribute('data-type', people.department);
        // get card content
        card.innerHTML = `
          <h5>${people.name}</h5>
          <p>${people.job}</p>
        `;  
        // display card
        document.querySelector('.directory-container').appendChild(card);
    });
}

renderDirectory(peoples);

jQuery(document).ready(function($) {
  $("#department-type").on("change", function(e) {
      e.preventDefault();
      var selectedDept = $(this).children("option:selected").val();
      console.log('selected value', selectedDept);
      $(".directory-container .card-body").each(function() { 
            // console.log("card-body", this);
            var department = $(this).attr("data-type");
            // console.log(selectedDept)
            console.log(department)
            if(department.indexOf(selectedDept) !== -1) {
                $(this).show();
                $(this).prop('selected', true);
            } else {
                $(this).hide();
            }
      });
  });
});

Solution

  • You are almost success,the reason is that selectedDept and department are not the same case ,so department.indexOf(selectedDept) will always return -1

    you need to change department.indexOf(selectedDept) to department.toLowerCase().indexOf(selectedDept)

    const peoples = [{
        name: 'Victor McGee',
        job: 'Dean of School',
        department: 'Dean of the office'
    },
    {
        name: 'Joe Pong',
        job: 'Academics',
        department: 'Admissions'
    },
    {
        name: 'Amy Baxter',
        job: 'Professor',
        department: 'Faculty'
    }];
    
    // console.log(peoples);
    
    const renderDirectory = function(peoples) {
    
        peoples.forEach(function(people) {
            // create card element/wrapper
            const card = document.createElement('div');
            card.classList = 'card-body'
            card.setAttribute('data-type', people.department);
            // get card content
            card.innerHTML = `
              <h5>${people.name}</h5>
              <p>${people.job}</p>
            `;  
            // display card
            document.querySelector('.directory-container').appendChild(card);
        });
    }
    
    renderDirectory(peoples);
    
    jQuery(document).ready(function($) {
      $("#department-type").on("change", function(e) {
          e.preventDefault();
          var selectedDept = $(this).children("option:selected").val();
          //console.log('selected value', selectedDept);
          $(".directory-container .card-body").each(function() { 
                // console.log("card-body", this);
                var department = $(this).attr("data-type");
                //console.log(department.toLowerCase().indexOf(selectedDept))
                if(department.toLowerCase().indexOf(selectedDept) !== -1) {
                    $(this).show();
                    $(this).prop('selected', true);
                } else {
                    $(this).hide();
                }
          });
      });
    });
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="styles.css">
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
        <title>People Directory</title>
    </head>
    <body>
        <h1 class="page-title">Directory</h1>
        <div>
            <label for="department-type">Department</label>
            <select name="department" id="department-type">
                <option value="" disabled selected>-Any-</option>
                <option value="dean of the office">Dean of the Office</option>
                <option value="admissions">Admissions</option>
                <option value="faculty">Faculty</option>
            </select>
        </div>
        <div class="directory-container"></div>
    </body>
    </html>