This App was develop as a Flatiron School JS project. I developed this app to help users create cryptocurrencies watchlists where they can see updated data from their favorite coins.
Back End Setup:
Note: You may refer to my previous Rails project for more detailed information on Rails, click the following link to find useful information about the API I'm using and more details FlatCoin on Rails.
I easily created my back end running:
rails new js_watchlist_backend --api
I generated my models via scaffold
:
rails generate scaffold coin coin_api_id name symbol
rails generate scaffold watchlist name description
rails generate scaffold watchlistCoin coin:references watchlist:references
Check out my back end repository here on GitHub!
Front End:
This is a single page Application (SPA), so a basic front end JS setup will have an index.html
, index.css
and index.js
.
Learning JS from scratch in one month was very challenging but after days of heavy debugging I realized that it's just a matter of understanding how to communicate with the backend API via fetch
.
I started out by creating editing my index.js
file.
let editMode = false
let addWatchlist = false
let divWatchlistCollection = document.querySelector('#watchlist_collection')
const flatcoinWatchlistAdapter = new FlatcoinWatchlistAdapter(`http://127.0.0.1:3000/`)
const flatcoinCoinAdapter = new FlatcoinCoinAdapter(`http://127.0.0.1:3000/`)
const watchlistForm = new WatchlistForm
const coinlistForm = new CoinForm
// Creating a global variable for coinFormContainer
const coinFormContainer = document.getElementById("coin_form_container")
//Creating a global variable for Back to watchlist btn
const backToWatchlistBtn = document.getElementById("back_watchlist_btn")
// Creating a global variable for Watchlist Collection
const watchlistCollection = document.getElementById("watchlist_collection")
// Creating a global variable for Watchlist Form container
const watchlistFormContainer = document.getElementById("watchlist_form_container")
// Creating a global variable for Coin Collection
const coinCollection = document.getElementById("coin_collection")
// Creating a global variable for New Watchlist Btn
const newWatchlistBtn = document.getElementById("new_watchlist_btn")
// Creating a global variable for Coin Container
const coinContainer = document.getElementById("coin_form_container")
// Creating a global varial for Watch list created Confirmation Container
const confirmationContainer = document.getElementById("watchlist_created_confirmation")
// Creating a global varial for Watch list deleted Confirmation Container
const confirmationDeleteContainer = document.getElementById("watchlist_deleted_confirmation")
// Creating a global varial for Watch list updated Confirmation Container
const confirmationUpdateContainer = document.getElementById("watchlist_updated_confirmation")
// Creating a global varial for Coin Delete Confirmation
const confirmationCoinDeleteContainer = document.getElementById("coin_deleted_confirmation")
coin_created_confirmation
// Creating a global varial for Coin Create Confirmation
const confirmationCoinCreateContainer = document.getElementById("coin_created_confirmation")
// DOM
document.addEventListener("DOMContentLoaded", () => {
watchlistForm.addCreateForm()
flatcoinWatchlistAdapter.getWatchlists()
watchlistForm.listenViewEditDelete()
displayWatchlistForm()
displayCoinCollection()
displayGoBackWatchlists()
handleGoBackWatchlists()
})
// Display Watchlist NEW and UPDATE form
function displayWatchlistForm() {
newWatchlistBtn.addEventListener("click", () => {
addWatchlist = !addWatchlist
if (addWatchlist) {
newWatchlistBtn.innerText = "Never mind!"
watchlistFormContainer.style.display = "block"
editMode = false
// watchlistForm.addCreateForm()
} else {
watchlistFormContainer.style.display = "none"
newWatchlistBtn.innerText = "Create a new Watchlist!"
}
})
}
// Displaying Coin Collection
function displayCoinCollection() {
coinCollection.style.display = "none"
}
// Displaying 'Go back to Watchilists!' btn
function displayGoBackWatchlists() {
backToWatchlistBtn.style.display = "none"
}
//
function handleGoBackWatchlists() {
backToWatchlistBtn.addEventListener("click", () => {
// console.log("Go back baby")
// Displaying Create New Watchlist
newWatchlistBtn.style.display = "block"
// Displaying Watchlist Collection
watchlistCollection.style.display = "block"
//Hiding Back to Watchlists btn
backToWatchlistBtn.style.display = "none"
//
coinContainer.style.display = "none"
// Displaying Coins
coinCollection.style.display = "none"
clearCoinCollectionAndForm()
})
}
// Testing area
// confirmationContainer.hide()
// setTimeout(function(){confirmationContainer.style.display = "none"}, 1000)
function clearCoinCollectionAndForm() {
while (coinCollection.firstChild) {
coinCollection.removeChild(coinCollection.firstChild)
}
while (coinFormContainer.firstChild) {
coinFormContainer.removeChild(coinFormContainer.firstChild)
}
}
Then I created an Adapter class for Watchlists, this handles all fetch requests.
class FlatcoinWatchlistAdapter {
constructor(baseURL) {
this.baseURL = baseURL
}
// Fetch Watchlist Function
getWatchlists() {
fetch(this.baseURL + `watchlists`)
.then(res => res.json())
.then(watchlists => {
watchlists.forEach(watchlist => {
// console.log(watchlist)
const w = new Watchlist(watchlist)
//console.log(w)
w.addToDom()
})
})
}
// Create new Watchlist
createWatchlist(nameInput, descriptionInput) {
fetch(this.baseURL + `watchlists`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify({
name: nameInput.value,
description: descriptionInput.value
})
})
.then(resp => {
console.log(resp)
return resp.json()
})
.then(data => {
console.log(data.message)
if (data.status === 201) {
const s = new Watchlist(data.watchlist)
s.addToDom()
// alert(data.message)
} else {
alert(data.errors)
}
nameInput.value = ""
descriptionInput.value = ""
newWatchlistBtn.click()
confirmationContainer.style.display = "block"
setTimeout(function(){confirmationContainer.style.display = "none"}, 1500)
})
.catch(err => console.error(err))
}
}
Then a Watchlist Class.
class Watchlist {
static all = []
constructor({id, name, description, created_at}) {
this.id = id
this.name = name
this.description = description
this.created_at = created_at
Watchlist.all.push(this)
}
render() {
return(`<div class="box" id="watchlist-${this.id}" data-id=${this.id}>
<h2>${this.name}</h2>
<p>${this.description}</p>
<p>${this.created_at}</p>
<button data-action='view'>View</button>
<button data-action='edit'>Edit</button>
<button data-action='delete'>Delete</button>
</div>`
)
}
addToDom() {
divWatchlistCollection.innerHTML += this.render()
}
}
And finally a WatchlistForm Class.
class WatchlistForm {
constructor(){
this.handleSubmit = this.handleSubmit.bind(this)
this.handleViewEditDelete = this.handleViewEditDelete.bind(this)
}
addCreateForm() {
const watchlistFormContainer = document.getElementById("watchlist_form_container")
const form = document.createElement('form')
form.innerHTML = `<input id="name_input" placeholder='Name' type='text'/><br>
<input id="description_input" placeholder='Description' type='text'/><br>
<input id="watchlist_submit" value="Create Watchlist!" type="submit"/>`
watchlistFormContainer.append(form)
form.addEventListener("submit", this.handleSubmit)
}
handleSubmit(event) {
event.preventDefault()
const nameInput = event.target[0]
const descriptionInput = event.target[1]
if (editMode){
flatcoinWatchlistAdapter.editWatchlist(editMode, nameInput, descriptionInput)
} else {
flatcoinWatchlistAdapter.createWatchlist(nameInput, descriptionInput)
}
}
listenViewEditDelete() {
const watchlistCollection = document.getElementById("watchlist_collection")
watchlistCollection.addEventListener("click", this.handleViewEditDelete)
}
handleViewEditDelete(event) {
const div = event.target.parentElement
console.log(div)
const action = event.target.dataset.action
console.log(action)
switch (action) {
case "delete":
flatcoinWatchlistAdapter.deleteWatchlist(div)
break
case "edit":
editMode = div
watchlistFormContainer.style.display = "block"
newWatchlistBtn.style.display = "none"
// const watchiListSubmitBtn = document.getElementById("watchlist_submit")
// watchiListSubmitBtn.value = "Update"
document.getElementById("watchlist_submit").value = "Update"
// Populate input
document.getElementById('name_input').value = div.children[0].innerText
document.getElementById('description_input').value = div.children[1].innerText
break
case "view":
// Hidding Create New Watchlist
newWatchlistBtn.style.display = "none"
// Hidding Watchlist Collection
watchlistCollection.style.display = "none"
//Displaying Back to Watchlists btn
backToWatchlistBtn.style.display = "block"
// Displaying Coin Form
// const coinlistForm = new CoinForm
coinlistForm.addCreateForm(div.children[0].innerText, div.dataset.id)
// const coinContainer = document.getElementById("coin_form_container")
coinContainer.style.display = "block"
// Displaying Coins
coinCollection.style.display = "block"
console.log(div)
// const flatcoinCoinAdapter = new FlatcoinCoinAdapter(`http://127.0.0.1:3000/`)
flatcoinCoinAdapter.getCoinlist(div)
// Adding an event listener for delete
coinlistForm.listenDelete()
default:
break
}
}
}
The logic for Coin object is the same as the watchlist, you may check out my front end repository here on GitHub for the full code.
Check out a quick YouTube video of my application.
Top comments (0)