Project #4 — Javascript

I can’t believe I’ve made it to my fourth project. I look back and think about how much I have learned so far and it blows my mind. It makes me feel motivated for the future.

Overview

This is my 4th project for Flatiron School’s SE program. We are required to make a Single-Page-Application with Ruby-on-Rails as an API for the backend and Javascript frontend. This was our first introduction to Javascript in the program.

It took me a while to come up with an idea. 4 projects under my belt now, I’ve noticed a common issue with all of them so far: coming up with an idea interesting yet simple enough to achieve with the knowledge I have. Ultimately, I decided to create a project called “Marvel Mayhem”. The idea is that a user can create a team and add characters for their own Avengers team. As someone who loves Marvel, I was excited to create this project.

To start, I decided to create two repositories — one for the frontend, and one for the backend. I felt like it was easier for me to keep the two separate while I get the hang of JS. The backend was pretty simple to set up and once that was relatively completed, I was able to move on to the JS portion of the project.

Create Action

One of the biggest obstacles I had to overcome during the project was having the ability to create a character that was associated with a team. In the beginning, I hard coded a team_id to make it easier to focus on getting createCharacters() working and then I refactored it to give the ablity to select from a dropdown to pick the team.

createCharacter() {
const character = {
name: document.getElementById("name").value,
description: document.getElementById("description").value,
thumbnail: document.getElementById("thumbnail").value,
team_id: 1
}
const configObj = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(character)
}
fetch(`${this.endpoint}/characters`, configObj)
.then(resp = resp.json())
.then(character => {
const c = new Character(character)
c.addToDom()
})
}

Let’s break down this code:

createCharacter() {
const character = {
name: document.getElementById("name").value,
description: document.getElementById("description").value,
thumbnail: document.getElementById("thumbnail").value,
team_id: 1
}
....

To start with, this code is creating an object with the values for my params that I want to send over to my backend from the form I created. I orignially hard-coded the team_id.

const configObj = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(character)
}

Then, I am stating which type of method I want to use and since it’s a for a create action it will be a POST. Then headers is pointing to another object that shows what I am sending out which is ‘application/json’ and then body with the JSON.stringify. We have to turn the data into a string before sending it over. Then, we are actually sending which is the object I created earlier (character) as an argument.

....fetch(`${this.endpoint}/characters`, configObj)
.then(resp = resp.json())
.then(character => {
const c = new Character(character)
c.addToDom()
})
}

Lastly, “Fetch” takes in an argument, which is my URL endpoint from my API and the character object I want to create. After that, a “promise” is returned because fetch is run asynchronously so it gets sent over to the Web API stack and takes its’ time loading. A promise is a way to let us know that the request is being worked on. After that, “.then” is used directly after the fetch because we have to wait for the fetch request to return the data. We don’t want to try and use the data from the fetch request before it has fully run. “.then” is telling it what we want to do next. the first “.then” takes the response from the fetch request and we use an arrow function to JSONify it because the initial response isn’t accesible. And finally one more “.then” to utilize the JSON-ified code. Here I am creating a new instance of the Character class and then appending it to the DOM with another method. Okay.. now back to my issue. Now that I had my “create” working, I needed to figure out how to add Teams to the form.

Adding the Teams

I added a new “fetch” request to my TeamService.js file. Here the constructor is taking in the endpoint I have defined in my Index.js to use a property for when a new instance of the class TeamService takes place. After that, I have a fetch request. My data is a nested object because of how fast_jsonapi structures it.

I wanted to be able to grab the all the data together, the team.id and the rest of the attributes are not on the same level in the nested object so I used the spread operator to grab the team.attributes and make a copy without changing the originial set of attributes and used that as the properties.

class TeamService {
constructor(endpoint) {
this.endpoint = endpoint
}
getTeams() {
fetch(`${this.endpoint}/teams`)
.then(r => r.json())
.then(data => {
data["data"].forEach((team) => {
const t = new Team({id:team.id, ...team.attributes})

t.addOnDom()
t.addToForm()
})
})
}

and I created a new instance of this class in my Index.js file

teamService.getTeams()

and lastly, I added the option to choose a team in my form with this method:

Class Team {static all = []    constructor({id, name }){        
this.id = id
this.name = name
this.element = document.createElement('div')
Team.all.push(this)
}
///more code here...addToForm() {
const option = document.createElement('option');
option.value = this.id;
option.innerText = this.name;
document.getElementById("team-dropdown").appendChild(option)
}
}

The addToForm() is creating a constant variable which is a new element of ‘option” and then the option.value will be the ID of the team that will being added to the form. the option.innerText will show as the name of the team. Finally, the team-dropdown element is selected and each team is appended to the form! SUCCESS!

Now my refactored createCharacters() looks like this:

createCharacter() {
const character = {
name: document.getElementById("name").value,
description: document.getElementById("description").value,
thumbnail: document.getElementById("thumbnail").value,
team_id: document.getElementById("team-dropdown").value
}const configObj = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(character)
}
fetch(`${this.endpoint}/characters`, configObj)
.then(resp = resp.json())
.then(character => {
const c = new Character({id:character.data.id, ...character.data.attributes})
c.addToDom()
})
}

Finally, the team-dropdown element is selected and each team is appended to the form! SUCCESS!

In Javascript, there are endless ways to end up with the same result, however, I am happy with the structure of my project and how it ended up!

REPO: https://github.com/dayshajones/marvel_mayhem_project

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store