Book Journey — JavaScript Project

Amanda
4 min readJul 1, 2021

--

For our fourth project at Flatiron, we were ask to build a single page application using JavaScript as the front end and a Rails API as the backend. My single page application idea was to have a page showing books people have recently read, as well as some recommendations if a person liked a particular book. There is the ability to “like” a book, so users can see what the most popular books are via how many likes it has.

Setting up the backend

Setting up the backend was relatively painless — rails has most of it already laid out for you if you use the scaffold option when creating models. My two models are: a Book model and a Recommendation model. The relationships are: books have many recommendations, and a recommendation belongs to a book. I pulled books from a few different end points of the New York Times books API and seeded the data into my database.

Dealing with the asynchronous nature of JavaScript

As I started building my webpage, I decided I wanted to list book recommendations underneath their respective books. Since JavaScript doesn’t have the same handy methods ActiveRecord does, I needed to think a bit about how to display these associations properly. I started with a method in the recommendation class to find all recommendations associated with the passed in bookId

recommendation.js

I was then able to call this method in the book class like so:

book.js

By passing in “this.id” (“this” referring to a particular book) to filterRecommendations, I was able to grab an array of all the recommendations associated with a given book. I then mapped over this array and returned the HTML I wanted generated for each recommendation. I was then able to append the recommendation to the DOM.

book.js

It was important to use an arrow function here to preserve the value of “this”. I used a for loop to iterate over the array returned from bookRecommendations and appended the recommendation to the correct book (again, utilizing this.id).

Initially, I added the appendRecommendationsToDOM method in my fetch method hoping that when the books were appended to the DOM, the recommendations would also be added.

bookService.js

This was not the case, however. Because of the asynchronous nature of JavaScript, even though I was calling my getRecommendations method before the getBooks method in index.js, there were still cases where getBooks would run first, leaving the Recommendation.all array empty and having nothing to iterate over. Other times, it would work as intended. This was frustrating to have something work part of the time, but not all of the time

index.js

I decided to change the way I was displaying my recommendations. I added a “show page” functionality by attaching an event listener to the book image so that when it is clicked, you can view only the selected book. Here is where I added the appendRecommendationsToDOM function, because it was guaranteed that both the books and recommendations had been fetched at this point.

Sorting Books by “most-liked”

Another functionality I added to my application was the ability to sort books from most to least liked. I attached an event listener to a button, with the following callback function:

book.js

I grabbed all the books and sorted over them, moving a book further down the array if it had less likes than the book it was being compared to. When I initially set this code up, I did not have the line “sortedBooks[i].element.innerHTML = “” ”.

I assumed clearing the booksContainer would be sufficient. However, when I ran my code it was duplicating the HTML inside each book div. After debugging, it was found that sortedBooks[i].element already contained HTML inside of it. Adding the above line solved the duplicating issue and the button now works as I intended it to.

Overall, this was a fun an challenging project to complete. I found JavaScript to be a bit unintuitive at times (coming from a Ruby background), but practicing definitely helped. I would not have survived without the debugger tool and console.log, constantly checking what “this” was returning. If you would like to learn more about this project, here is the github link and a short demo video.

--

--