Filtering data from fetch() into matching container

960 Views Asked by At

I'm using fetch() to create a section which pulls and sorts listings from greenhouse api into its matching container.

I have a predefined list of departments which I have stored in the departments array. If a fetched item has a similar value as the data-dept value, then that html will be added under that container.

Here's an example, one of the items in the array is "Sales". Once fetch() is complete, two things can happen:

  1. Either a job with the department of "sales" exists, in which case it will be appended to data-dept="sales". Note: In my code, I'm using data-dept^= to find similar names. If "sales us" exits in the api, then I want that too to be appended to [data-dept="sales"].
  2. No jobs exist with the department of "sales". In this case, if "[data-dept="sales"]` has no child elements, hide it, as there's no point showing departments with no listings.

Current issues:

  1. You can see by accessing the API URL that jobs with the "department" of "sales" do exist, but they do not get appended to my data-dept="sales" div (it has no child elements).
  2. Any jobs that are not similar departments to those that are in the array need to appended to data-dept="other", but this section is also empty. For example, thee api has jobs for the "department" of "Architects". This option isn't in the array, so these jobs will need to be appended to data-dept="other".

Code:

$(function() {

  fetch('https://boards-api.greenhouse.io/v1/boards/example/jobs?content=true', {})

  .then(function (response) {
    return response.json();
  })

  .then(function (data) {
    appendDataToHTML(data);
  })

  .catch(function (err) {
    console.log(err);
  });


  function appendDataToHTML(data) {

    const mainContainer = document.getElementById("careers-listing");

    // for each object, create card
    for (var i = 0; i <  Object.keys(data.jobs).length; i++) {

      var department = data.jobs[i].departments[0].name;
      department = department.replace(/\s+/g, '-').toLowerCase();
      var job_title = data.jobs[i].title;
      var job_location = data.jobs[i].location.name;

      var html =

        '<figure class="careercard" data-dept="'+ department +'">' +
          '<div class="careercard__inner">' +

            '<figcapton class="careercard__role">' +
              '<span class="careercard__title">' + job_title + '</span>' +
            '</figcapton>' +

            '<div class="careercard__address">' +
              '<span class="careercard__location">' + job_location + '</span>' +
            '</div>' +

          '</div>' +
        '</figure>';


        // filter card in correct parent category
        if ("[data-dept^="+ department +"]") {
          $(".careersIntegration__accordion-jobs[data-dept^='" + department + "']").append(html);

        } else{
          $(".careersIntegration__accordion-jobs[data-dept='other']").append(html);
        }

    }
  }

  /* fetch end */

  $('.careersIntegration__accordion-jobs').each(function(index, obj){
    console.log(this);
    if ( $(this).length == 0 ) {
      console.log("hide");
    } else{
      console.log("dont hide");
    }
  });


});
{% set departments = ["Sales" "Technology", "Creative", "Other"] %}

<section class="careersIntegration">
  <div class="careersIntegration__listing" id="careers-listing">

    {% for dept in departments %}
      <div class="careersIntegration__accordion">
      
        <div class="careersIntegration__accordion-header">
          <span class="careersIntegration__accordion-dept">{{ dept }}</span>
        </div>
        
        <div class="careersIntegration__accordion-jobs" data-dept="{{ dept|lower|replace( ' ', '-' ) }}"></div>
        
      </div>
    {% endfor %}

  </div>
</section>

Here is a visual guide of the layout I'm trying to achieve if it helps:

enter image description here

1

There are 1 best solutions below

0
On

So this is not an exact answer but it does give you a good example. I just used mock data but here is the idea. Im sure there is a better way to do this but this is the quick and dirty.

  1. Create a few variables to store the data for each department. This is a filter function that just stores anything inside the include() this will allow you to catch something like "US Sales" in the sales department.
  2. Create a map function that takes in two paramiters the first is the variable you created earlier and the second is the name of the department which should match the name of whereever you are going to append this information.
  3. The first part of the function creates the item using a template literal. this will create an array of all the items
  4. The second part of the function wraps the array in a UL which is not super important but what is important is that you join the array using an empty sting.
  5. Last part simply appends the html to the end of the department by using the name of the department as an ID and .insertAdjacentHTML("beforeend", list) which puts it before the end of the element and passes in the HTML which I have named as list

const data = [
  {
    title: "Lead Sales Person",
    dept: "sales",
    desc: "be a leader"
  },
  {
    title: "Sales Person",
    dept: "sales",
    desc: "sell stuff to people"
  },
  {
    title: "US Sales Person",
    dept: "sales US",
    desc: "sell stuff to people"
  },
  {
    title: "Lead Developer",
    dept: "dev",
    desc: "be a leader"
  },
  {
    title: "Developer",
    dept: "dev",
    desc: "Develop things and stuff"
  },
  {
    title: "Random Guy",
    dept: "other",
    desc: "Do Random Stuff"
  },
  {
    title: "Random Girl",
    dept: "other",
    desc: "Do Random Stuff"
  }
];

let sales = data.filter(job => job.dept.includes("sales")),
dev = data.filter(job => job.dept.includes("dev")),
other = data.filter(job => job.dept.includes("other"));

mapDepartment(sales, "sales");
mapDepartment(dev, "dev");
mapDepartment(other, "other");

function mapDepartment(dept, name){
  let items = dept.map(position => {
    return `
      <li>
        <b>Title:</b> ${position.title}<br>
        <b>Description:</b> ${position.desc}
      </li>
    `
  })
  let list = `<ul>${items.join("")}</ul>`;
  document.getElementById(name).insertAdjacentHTML("beforeend", list)
}
ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

li {
  margin-bottom: 1rem;
}
<div id="sales">
  <h1>Sales</h1>
</div>
<div id="dev">
  <h1>Development</h1>
</div>
<div id="other">
  <h1>Other</h1>
</div>