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>