Home > database >  Trying to filter 4 different houses from an api
Trying to filter 4 different houses from an api

Time:04-04

I'm trying to separate characters based on what house they belong to in the API (http://hp-api.herokuapp.com/api/characters)

I have tried using .filter and .map, but have been unable to achieve that goal, I don't know if this is the right place to ask for help understanding how to achieve my goal.

Here is the code:

const studentArray = [];

async function getStudents(url) {
  const student = await fetch(url);
  const jsondata = await student.json();
  jsondata.forEach((student) => {
    studentArray.push(student);
  });
}

getStudents("http://hp-api.herokuapp.com/api/characters/students").then(() => {
});
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="/testing/script.js"></script>
    <link rel="stylesheet" href="/testing/styles.css" />
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <main>
      <div id="name" ><button onclick="Gryffindor">Test</button></div>
      <div id="name" ><button onclick="Slytherin">Test</button></div>
      <div id="name" ><button onclick="Ravenclaw">Test</button></div>
      <div id="name" ><button onclick="Hufflepuff">Test</button></div>
    </main>
  </body>
</html>

CodePudding user response:

I've just had a look here and there seems to already be an endpoint set up to get characters from particular houses if that's what you want to do?

E.g. fetch(http://hp-api.herokuapp.com/api/characters/house/gryffindor) will return an array of students in Gryffindor.

You could refactor your getStudents function to take the house as an argument and make a GET request to the http://hp-api.herokuapp.com/api/characters/house/:house endpoint, using a template literal.

Also your onClick isn't invoking any function. I suggest you have a look here for an example of how to use onClick

CodePudding user response:

function emptyElementNode(elmNode) {
  [...elmNode.childNodes].forEach(node => node.remove());
}

function createHouseFilterItem(houseName) {
  houseName = houseName.trim();

  const elmItem = document.createElement('li');
  const elmButton = document.createElement('button');

  elmItem.dataset.filterLabel = houseName;
  elmButton.textContent =
    (houseName === '') && 'No House' || houseName;

  elmItem.appendChild(elmButton);
  return elmItem;
}
function createStudentItem(studentData) {
  const elmItem = document.createElement('li');
  const elmImage = document.createElement('img');
  
  elmImage.src = studentData.image;
  elmImage.alt = studentData.name;

  elmItem.appendChild(elmImage);
  return elmItem;  
}

function renderStudentsByHouseFilter(houseBasedIndex) {
  const houseNameList = Object.keys(houseBasedIndex);
  // console.log({ houseNameList });

  const filterRoot = document
    .querySelector('[data-students-filter]');

  if (filterRoot) {

    const filterListRoot = houseNameList
      .reduce((rootNode, houseName) => {

        rootNode
          .appendChild(
            createHouseFilterItem(houseName)
          );
        return rootNode;

      }, document.createElement('ul'));

    const allHousesFilterItem =
      createHouseFilterItem('All Students');

    allHousesFilterItem.dataset.filterLabel = 'all-students';

    filterListRoot.appendChild(allHousesFilterItem);
    emptyElementNode(filterRoot);
    filterRoot.appendChild(filterListRoot);

    return filterRoot;
  }    
}
function renderStudentsByHouse(studentList) {
  const displayRoot = document
    .querySelector('[data-student-list]');
 
  if (displayRoot) {

    const listRoot = studentList
      .reduce((rootNode, studentData) => {

        rootNode
          .appendChild(
            createStudentItem(studentData)
          );
        return rootNode;

      }, document.createElement('ul'));

    emptyElementNode(displayRoot);
    displayRoot.appendChild(listRoot);
  }
}

function handleStudentsFilterFromBoundIndex({ target }) {
  const filterItem = target.closest('li[data-filter-label]')
  const { dataset: { filterLabel } } = filterItem;
  // console.log({ filterItem, filterLabel });

  const studentList = this[filterLabel];
  renderStudentsByHouse(studentList);
}
function initializeStudentsFilterHandling(filterRoot, houseBasedIndex) {
  filterRoot
    .addEventListener(
      'click',
      handleStudentsFilterFromBoundIndex.bind(houseBasedIndex)
    );
}

function createStudentsByHouseFilter(studentList) {
  const houseBasedIndex = studentList
    .reduce((index, student) => {

      const houseName =
        student.house?.trim() ?? '';

      (index[houseName] ??= []).push(student);
      return index;

    }, {});

  // console.log({
  //  studentList,
  //  houseBasedIndex,
  // });
  const filterRoot = renderStudentsByHouseFilter(houseBasedIndex);

  houseBasedIndex['all-students'] = studentList;

  initializeStudentsFilterHandling(filterRoot, houseBasedIndex);
}

async function main() {
  const url = 'http://hp-api.herokuapp.com/api/characters/students';

  const response = await fetch(url);
  const studentList = await response.json();

  createStudentsByHouseFilter(studentList);
}
main();
ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
}
ul li {
  display: inline-block;
  margin: 0 5px 5px 5px;
}
ul li img {
  height: 130px;
  width: auto;
}
<article data-students-overview>

  <navigation data-students-filter>
    <em>    initialize house based students filter    </em>
  </navigation>

  <section data-student-list>
  </section>

</article>

  • Related