Furmiliar: JS Project
Tags: beginners, javascript, webdev, rails
Published: 2022-01-14 23:56:41

I have finally finished my JavaScript final project for the Flatiron bootcamp. I will say that this project has been by far the most challenging yet. The project had to have a Rails API with a HTML, CSS, and vanilla OO JS frontend. All aspects of processing data had to be done via JS. Trying to do forms and talk with the API was the most important aspect of the project, but most of the course material didn’t cover this at all. I had to watch multiple tutorials to get a grasp on how to approach this. A lot of the labs in this section towards the end were really lacking. I did learn a lot from doing this project but still feel shaky about my knowledge of JS.  With most of my coding adventure so far, the more you learn, the more you realize what you don’t know. 

The use case for my project is an app for pet owners to keep track of toys their pets did and didn’t like. Each pet has a toy box and that toy box contains all the toys for that pet. With the toy boxes and toys, there is full CRUD. The add toy form only pops up when you have opened a toy box so no toys can be added without an associated box. 

A big aspect of this project was to do DOM manipulation on a SPA. Doing this aspect was fun and I tried to mainly use variables as I personally like it more than just rendering everything with `.innerHTML`. I did one of my methods with `.innerHTML` just to show that I knew how to do it.
``` JS
addToDom(){
        const toyBoxDiv = document.getElementById("toy-box")
        const toyBoxCard = document.createElement("div")
        toyBoxCard.className = "toy-box-card"
        toyBoxCard.setAttribute("data-id", `${this.id}`)
        const photoBox = document.createElement("img")
        photoBox.src = this.photo
        photoBox.className = "toy-box-photo"
        const toyBoxName = document.createElement("h2")
        toyBoxName.innerText = this.name
        const openToyBox = document.createElement("button")
        openToyBox.innerText = "Open Toy Box" 
        openToyBox.setAttribute("id", `toy-box-button-${this.id}`)
        openToyBox.setAttribute("data-action", "open")
        openToyBox.addEventListener("click", this.openEvent)
        const deleteToyBox = document.createElement("button")
        deleteToyBox.innerHTML = "&#10006"
        deleteToyBox.setAttribute("id", "toy-box-delete")
        deleteToyBox.setAttribute("data-action", "delete")
        const editToyBox = document.createElement("button")
        editToyBox.innerHTML = "&#9999"
        editToyBox.setAttribute("id", "toy-box-edit")
        editToyBox.setAttribute("data-action", "edit")
        toyBoxDiv.appendChild(toyBoxCard)
        toyBoxCard.appendChild(photoBox)
        toyBoxCard.appendChild(toyBoxName)
        toyBoxCard.appendChild(openToyBox)
        toyBoxCard.appendChild(deleteToyBox)
        toyBoxCard.appendChild(editToyBox)
    }
// versus innerHTML
createToyForm(toyBoxAssociation){
        const toyFormContainer = document.getElementById("toy-form")
        toyFormContainer.innerHTML = ""
        toyFormContainer.style.display = "inline-block"
        const toyForm = document.createElement("form")
        toyForm.innerHTML = `<h2>Add a New Toy</h2>
            <input type="text" id="toy-photo-input" placeholder="Photo URL">&emsp;
            <input type="text" id="toy-name-input" placeholder="Name">&emsp;
            <input type="text" id="toy-brand-input" placeholder="Brand">&emsp;
            <input type="text" id="toy-price-input" placeholder="Price">&emsp;
            <input type="text" id="toy-url-input" placeholder="Website URL">&emsp;
            <input type="text" id="toy-rating-input" placeholder="Rating 1-5">&emsp;<br><br>
            <strong>Needs Repair?</strong> <input type="radio" id="toy-needs-repair-input-true" name="needs-repair" value="true">True
            <input type="radio" id="toy-needs-repair-input-false" name="needs-repair" value="false">False &emsp;
            <strong>Squeaker?</strong> <input type="radio" id="toy-squeaker-input-true" name="squeaker" value="true">True
            <input type="radio" id="toy-squeaker-input-false" name="squeaker" value="false">False &emsp;
            <strong>Crinkle?</strong> <input type="radio" id="toy-crinkle-input-true" name="crinkle" value="true">True
            <input type="radio" d="toy-crinkle-input-false" name="crinkle" value="false">False &emsp;
            <strong>Hides Treats?</strong> <input type="radio" id="toy-treat-input" name="treat" value="true">True
            <input type="radio" name="treat" value="false">False &emsp;<br><br>`

        const addToyBoxId = document.createElement("input")
        addToyBoxId.setAttribute("type", "hidden")
        addToyBoxId.setAttribute("name", "toy-box-id")
        addToyBoxId.setAttribute("id", "toy-box-id-input")
        addToyBoxId.value = `${toyBoxAssociation}`

        const submit = document.createElement("button")
        submit.setAttribute("id", "toy-submit")
        submit.setAttribute("type", "submit")
        submit.setAttribute("value", "Add Toy")
        submit.innerText = "Add Toy"

        toyForm.appendChild(addToyBoxId)
        toyForm.appendChild(submit)
        toyFormContainer.append(toyForm)

        toyForm.addEventListener("submit", this.toySubmit)
    }

```

One thing that really tripped me up on my project was in my fetch requests I was initially told that since I had a nested array of attributes that I needed to use dot notation on the data I was receiving to access it. I asked several people to figure out what was going on and the third person I asked was finally able to help me. It was odd because in debugger the response was just CORS, which made no sense to anyone and I am still puzzled why calling `data.toys` instead of `data` would return CORS.  

Another thing that I struggled with were the radio buttons. I had a hard time finding good documentation on vanilla JS handling radio buttons. Handling radio buttons with Rails was so easy and JS proved to be a lot more challenging. That is one aspect I one day want to revisit is fixing my radio buttons. I really wanted for when you edit a toy, the radio buttons are filled in with the information from the API. I couldn’t find an elegant solution that was DRY. 

I found it helpful to go through my code and console log every function as it was hit. I figured I would provide that breakdown as well. I broke down each action and stated the class that each method is from and the method name. The classes I have are toyBoxAdapter and toyAdapter which deal with the fetch requests for those objects, toy and toyBox, and toyForm and toyBoxForm for the forms associated with those classes. You can view all of my code [on my github](https://github.com/dotnotation/Furmiliar_Frontend)

upon initial load
- DOMContent Loaded
- toyBoxAdapter fetchToyBoxes
- toyBoxForm createToyBoxForm
- toyBoxForm listenEvents
- toyForm listenToys
- toyBox addToDom

creating a toyBox
- toyBoxForm handleSubmit
- toyBoxAdapter createToyBox
- toyBox addtoDom

editing toyBox
- toyBoxForm handleEvents
- toyBoxForm handleSubmit
- toyBoxAdapter editToyBoxes

deleting toyBox
- toyBoxForm handleEvents
- toyBoxAdapter deleteToyBox

open toyBox
- toyBox openEvent
- toyBox getToys
- toy renderToys
- toyForm createToyForm
- toyBoxForm handleEvents

add toy
- toyForm toySubmit
- toyAdapter createToy
- toy renderToys

edit toy
- toyForm toyEvents
- toyForm toySubmit
- toyAdapter editToy
- toyForm toySubmit

delete toy
- toyForm toyEvents
- toyAdapter deleteToy

If you are interested in the [backend](https://github.com/dotnotation/Furmiliar_Backend) of my app. I just used `rails new project_name --api` to create the backend of my app and kept most things the same from the auto-generated code. 

 Now with this project wrapped, I have to prepare for the assessment. I have been studying and practicing but still feel unprepared. I think I will just have to schedule the assessment and see how it goes. I have heard that this assessment is one of the most challenging. Wish me luck!