Learning Javascript (…again)
Before starting Flatiron I took the initiative to learn some Javascript. My independent study involved studying methods and creating functions that served small purposes like converting minutes to hours, basic variable assignments, or determining if a number was less than 100. By just scratching the surface I thought I was utilizing Javascript at its fullest. Looking back now I laugh at how far from the truth that was.
Embarking on the Phase 4 Javascript Single Page Application and Rails API project was one of the more challenging projects I’ve encountered since learning the basics of Ruby. Where I went wrong with how I taught myself Javascript in the beginning was by not learning Javascript dynamically. When studying before Flatiron I was unknowingly using Javascript single handedly (and basically in a vaccuum) without utilizing it’s full potential through the use of Rails, HTML, and CSS. Through this project I have a better grasp at how powerful and useful Javascript can be when accompanied with other languages (and markup languages).
A step that stumped me when learning this lesson was creating a drop down menu for my form. My project is called Record Wishlist. A user is able to compile a list of albums through a form containing extra info about an album. When a user has listened or bought the album on their list, they’re able to delete the album from the DOM. My problem lied in creating a dynamic drop down menu within the form that allows a user to add an album to their list. Coding with dynamism has never been my strong suit so far in Flatiron and I was very intimidated at tackling this problem after coming out of a barage of Ruby. The best approach was immediately dividing the tasks into smaller and more attainable goals.
GenreServices consists of the defined baseURL within the constructor. The baseURL is implemented into the fetch request which allows the front end to access information from the API backend. A fetch request is made to access data from the backend API. A fetch request follows a specific syntax where the fetch() consists on a single argument which is the resouce you want to retireve information from. A promise is returned which is resolved with a response object. If a fetch request is resolved without issue, the response object returns an HTTP response. To extricate the data we need from the API, we use json() that returns a second promise. Once the second promise is resolved, it returns the parsed response as JSON. In this case, we are grabbing the genres from the backend and iterating over each genre where a new instance is created. The attributes of a genre such as it’s name and genre_id are created through the methods renderGenre (which we define in the Genre class) and stored in the backend.
class GenreServices {constructor(baseUrl){this.baseUrl = baseUrl;};getGenres() {fetch(this.baseUrl) .then(resp => resp.json()) .then(genres => {console.log(genres)genres.forEach(genre => {const newGenre = new Genre(genre)newGenre.renderGenre();})})};};
A second class was created for Genre, following the has_many — belongs_to relationship where a genre has many albums and an album belongs to a genre. Within the class I added a constructor where the attributes are listed. The argument of the constructor are within curly brackets which follows the destructuring syntax. Destructuring allows one to identify values of an array or an object and reformat them as individual variables.
class Genre {constructor({id, name}) {this.id = id;this.name = name; }}
The next focus was creating a method that would render the genres for the drop down menu. Two variables were defined, the first being genreSelect which defines the element by it’s id ‘genre-menu’. The second variable is genreCard where a card for the genre drop down menu is created with an id of ‘option’. Using destructuring, we assign genreCard to this.name. This is similar as self in Ruby on Rails where this refers to the class itself. In this case, the assignment of genreCard.text will be the name of each genre. Then a value is assigned to genreCard using the .value method which is equal to the genre_id attribute. The last line of this method joins the genre drop down selections (genre name and genre_id) to the genreCard which is then appended to the drop down menu.
class Genre {constructor({id, name}) {this.id = id;this.name = name;}renderGenre() {const genreSelect = document.getElementById('genre-menu');const genreCard = document.createElement('option');
genreCard.text = this.namegenreCard.value = this.id;genreSelect.appendChild(genreCard);};};
In the index.html file, we render the genres and the drop down menu by embedding the id of the elements created into the form. Within the <select></select> tags the id of genre-menu is referenced
<form id="album-form"><input type="text" id="title" name="title" placeholder="Album Title" /><input type="text" id="artist" name="artist" placeholder="Artist" /><input type="text" id="year" name="year" placeholder="Year Released" />
<select id="genre-menu" name="genre-menu"><option value="">Select Genre:</option></select>
<button type="submit"> Create Album </button></form>
Genre id and genre name are within the genreCard which is appended to the genre-menu. This is a vastly dynamic way of creating a drop down menu to display a list of genres. If I chose to go into the backend and add more genres, the drop down menu would update it’s population without having to hardcode the new genre options into the index.html.
There are a lot of moving parts to Javascript and this first project. Some of the most important aspects of this project for me involved staying organized with project planning. It’s important to go into any project with a drawn out plan to prevent getting lost along the way. To avoid getting lost, I found using proper naming conventions for functions helped me keep track of methods and variables when they are invoked or defined. And most importantly, have patience, progress is not linear.