Problem on Book Finder Project

Hello,

I am doing the exam for the Book Finder Project. I completed the project, tested it multiple times but it doesn’t pass the second test. It says that my return array is returning 0 elements. However, when I console.log it, I can see the two element array.

const books = [
  {
    title: "The City We Became",
    author: "N. K. Jemisin",
    tags: ["fantasy", "fiction", "afrofutursim", "science fiction", "sci-fi"]
  },
  {
    title: "The Catcher in the Rye",
    author: "J. D. Salinger",
    tags: ["fiction", "young adult", "YA", "realism", "coming of age", "classic"]
  },
  {
    title: "The Hundred Thousand Kingdoms",
    author: "N. K. Jemisin",
    tags: ["fantasy", "fiction", "adventure", "series"]
  },
  {
    title: "Sapiens: A Brief History of Humankind",
    author: "Yuval Noah Harari",
    tags: ["nonfiction", "history", "anthropology", "science", "sociology"]
  },
  {
    title: "Behave: The Biology of Humans at Our Best and Worst",
    author: "Robert M. Sapolsky",
    tags: ["nonfiction", "anthropology", "science", "sociology", "biology"]
  },
  {
    title: "The Parable of the Talents",
    author: "Octavia Butler", 
    tags: ["fiction", "dystopian", "science fiction"]
  },
  {
    title: "1984",
    author: "George Orwell", 
    tags: ["fiction", "dystopian", "science fiction", "classics", "adult"]
  },
  {
    title: "Remarkably Bright Creatures",
    author: "Shelby Van Pelt",
    tags: ["fiction", "mystery", "magical realism"]
  },
  {
    title: "Crying in H Mart",
    author: "Michelle Zauner",
    tags: ["memoir", "nonfiction", "autobiography"]
  },
  {
    title: "Wild: From Lost to Found on the Pacific Crest Trail",
    author: "Cheryl Strayed",
    tags: ["nonfiction", "memoir", "adventure", "travel"]
  }
]

// Flatten object keys into an array so that we search the entire object by the input value
const flattenObjectValuesIntoArray = (arrOfObjs) => {
  let flattenedObj;
  const flattenedObjsArr = [];
  for (let obj = 0; obj < arrOfObjs.length; obj++) {
    const objValues = Object.values(arrOfObjs[obj]);
    flattenedObj = [...objValues.flat()]
    flattenedObjsArr.push(flattenedObj)
  }
  return flattenedObjsArr;
};

// Structure filtered books as HTML and return
const structureBookAsHtml = (book) => {
  const bookDiv = document.createElement("div");
  bookDiv.setAttribute('class', 'bookDiv');
  
  const bookTitle = document.createElement("h2");
  bookTitle.innerHTML = book.title;
  bookTitle.setAttribute('class', 'bookTitle');

  const bookAuthor = document.createElement("h3");
  bookAuthor.innerHTML = book.author;

  const bookTags = document.createElement("p");
  bookTags.innerHTML = book.tags.join(", ");

  bookDiv.append(bookTitle, bookAuthor, bookTags);
  
  return bookDiv;
};

const renderBooksToDom = (elements) => {
  const bookListContainer = document.querySelector("#bookList");
  bookListContainer.innerHTML = "";

  bookListContainer.append(...elements);
};

// Click handler for search button
const captureSearchValue = () => {
  let searchInput = document.getElementById('search-bar').value;
  return searchInput;
 };
 
 // Filter books based on search input
    const filterBooks = (searchString, listOfBooks) => {
      searchString = captureSearchValue();
      listOfBooks = books;
      let filteredList = [];
      for(let i=0; i<listOfBooks.length; i++) {
       let bookArr = flattenObjectValuesIntoArray(listOfBooks);
       if(bookArr[i].includes(searchString)) {
         filteredList.push(listOfBooks[i]);
       }
      }
      return filteredList;
    };
 
 // Empty the book list container, iterate over list of filtered books, return list of books formatted as HTML using the function in `helper.js` 
 const structureBooksAsHtml = (filteredBookList) => {
   return filteredBookList.map(book => structureBookAsHtml(book));
 };
 
 // Handler triggered when a user clickers the "Search" button. Chains previously defined functions together to filter books based on the search value, formats the books as HTML and renders them to the DOM
 const searchBtnClickHandler = (books) => {
   let searchValue = captureSearchValue();
   let filteredBooks = filterBooks(searchValue, books);
   let finalList = structureBooksAsHtml(filteredBooks);
   renderBooksToDom(finalList);
 }
 
 // Grab search button from the DOM
 const searchBtn = document.getElementById("search-btn")
 
 // Attach an event listener to the search button
 searchBtn.addEventListener("click", () => { searchBtnClickHandler(books) });
1 Like

I have the same problem. I’ve also console logged the test inputs and it’s not returning the test input that is throwing the error. But when I manually test it in the browser it works as expected. I’ve logged it as a bug as I’m not really sure what else to do here! :woman_shrugging:

2 Likes

I have the same issues, did you managed to get over it?

yea I managed to solve it, but my solution turned out to be different to the issue posted here. :confused:

could you please help< I am really stucked

I am not sure how much help I can give because this is part of the assessment… can you outline your problem and I’ll see what I can do?

// Click handler for search button
const captureSearchValue = () => {
const searchInput = document.getElementById(‘search-bar’);
return searchInput.value.toLowerCase();
};

// Filter books based on search input
const filterBooks = (searchValue, books) => {
return books.filter(book =>
book.tags.some(tag => tag.toLowerCase().includes(searchValue))
);
};

// Empty the book list container, iterate over the list of filtered books, return list of books formatted as HTML using the function in helper.js
const structureBooksAsHtml = (filteredBooks) => {
return filteredBooks.map(book => structureBookAsHtml(book));
};

// Handler triggered when a user clicks the “Search” button.
// Chains previously defined functions together to filter books based on the search value,
// formats the books as HTML, and renders them to the DOM
const searchBtnClickHandler = (books) => {
const searchValue = captureSearchValue();
const filteredBooks = filterBooks(searchValue, books);
const htmlElements = structureBooksAsHtml(filteredBooks);
renderBooksToDom(htmlElements);
};

// Grab search button from the DOM
const searchBtn = document.getElementById(‘search-btn’);

// Attach an event listener to the search button
searchBtn.addEventListener(“click”, () => { searchBtnClickHandler(books) });

Errors…
Given the filter YA, your filterBooks function returned an array with 0 elements. We expected it to return 1.
Given a search for 'fiction', expected the bookTitle div to have 6 child elements.

Looks like a couple of your functions are erroring and the error messages you are seeing are correct. Here are some general comments:

  • The .filter() method only works on arrays. Check back on the lessons / projects where this is covered for more tips on usage and syntax.
  • Read the instructions carefully. There are some helper functions provided that you can (and iirc should) use.
  • You can check what the return value of your function is by adding a console.log() statement in the function. Open up Developer Tools in your browser to see the outputs.

Hope that helps and good luck with the assessment!

I’m also struggling with the second function - just to check, are we trying to return just the name of the relevant books?

So where the search value is ‘fantasy’, then ‘The City We Became’ and ‘The Hundred Thousand Kingdoms’?

But not the entire arrays - i.e. not [‘The City We Became’, ‘N. K. Jemisin’, ‘fantasy’, ‘fiction’, ‘afrofutursim’, ‘science fiction’, ‘sci-fi’] and the same for ‘The Hundred Thousand Kingdoms’?

I’m getting the right book names but not passing the test - any guidance would be appreciated.

Thanks

Hi! I’m sorry but I can’t be too specific here as this is part of the assessment. But you should be able to work out the expected return value by looking at what’s going to happen to it next. Why are we getting the filtered books and what’s going to happen to the output of that function next? Hope that helps and sorry that I can’t be more specific. Good luck with it! :slight_smile:

1 Like

Thanks - I came back to it a few hours later and with fresh eyes realized where I’d gone wrong!

1 Like

Brill! Good luck with the rest! :slight_smile:

1 Like

I also passed the test. Thank you!

1 Like

congrats! well done! :slight_smile:

Hello, I am also facing the same issue.
Here is my function. This works perfectly when I run it manually.
// Filter books based on search input
let filterBooks = (books) => {
const filteredBooks = ;
const input = captureSearchValue();
let flattenedBooks = flattenObjectValuesIntoArray(books); // Call existing function
for (let book = 0; book < books.length; book++) {
// Search in the flattened books array, also make lowercase to include case insensitive results
if (
flattenedBooks[book]
.map((e) => e.toLowerCase())
.includes(input.toLowerCase())
) {
filteredBooks.push(books[book]);
}
}
return filteredBooks;
};

Any help is deeply appreciated.

Hi! I’m sorry that I can’t be too specific here as this project is part of your assessment. There are some instructions provided specific to this function. If you read them carefully you should be able to work out the rest. I hope that helps and sorry that I can’t be more specific. Good luck with your assessment!

1 Like

Hey, did you managed to work out?

I am struggling a lot, I’m feeling frustrated.