Great tutorial by Traversy Media – Link to the video
Has a form to let user add books (title, author, isbn) and then displays the books in a table below the form. You are able to delete an item but there is no edit or sorting functionality. Uses Bootstrap (actually bootswatch), font-awesome, and no frameworks.
Basic HTML Structure
Simple form with and id. Inside of the form are form-group divs that contain labels and inputs with various bootstrap classes. Under the form is a simple table containing thead and tbody.
Starts by mapping out the application in the app.js file.
// Book Class: Represents the Book
// UI Class: Handle UI Tasks
// Store Class: Handles Storage
// Event to Display Books
// Event to Add a Book
// Event to Remove a Book
Uses “static” keyword for methods in UI and Store Classes so he doesn’t have to instantiate classes.
Display Books by adding to UI – 13m
books.forEach((book) => {
UI.addBookToList(book)
})
static addBookToList(book) {
const list = document.querySelector(#book-list)
const row = document.createElement('tr')
row.innerHTML = `
<td>${book.title}<td>
<td>${book.author}<td>
<td>${book.isbn}<td>
<td><a href="#" class="btn btn-danger delete"></a><td>
`
list.appendChild(row)
}
// Event: Display Books
document.addEventListener('DOMContentLoaded', UI.displayBooks)
Note that the The DOMContentLoaded event fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets.
On the delete feature you can’t just target the delete button because it will only target the first one. So you have to use event propagation. Event propagation is where you add event listener to something above it and then target whatever is clicked inside of it using “e.target” and make sure it contains the class of you are looking for using “classList.contains()”
if (e.classList.contains("delete")) {
el.parentElement.parentElement.remove()
}
Target the list and then add a click listener and then console.log(e.target) to see the event parameter (anything that is clicked on). Pass “e.target” into a method called UI.deleteBook() and in the function block see if what was clicked contains a “delete” class then remove the parent of the parent.
if (e.classList.contains("delete")) {
el.parentElement.parentElement.remove()
}
Validation and Alerts
Making sure the field is not left blank is the only real validation here. Alerts are appended.
const div = document.createElement('div')
div.className = alert alert-${className}
div.appendChild(document.createTextNode(message))
To display grab parent element which is the container
container.insertBefore(div, form)
Use setTimeout to remove the alert after .3 seconds
Persist to Local Storage – 41m
Don’t forget need to use JSON.stringify and JSON.parse when saving to local storage.
localStorage.getItem()
localStorage.setItem()
// static getBooks
// static addBook
// static removeBook
Some good stuff in here. Some of the things I work confused with was the static keyword and then having three separate classes and using that in the setup that I had currently using web pack and modules.
Splitting the code in a separate files is fine You just need to import and instantiate.
I created a test drive form module and that’s what I instantiated in the main.js file. In the test drive form.js module I still had a car class but that was instantiated from within this file.
The local storage took a little time and I was able to use the custom data attribute for local storage. I was going to use the date object on when the item was created but May decide to just go with simple method random ID.
I do need to fix a bug on local storage in which if you create it and deleted before a page refresh it will be there after the first page refresh.
I also want to revisit the inner HTML strategy and maybe swap it out for insert adjacent HTML with the beforeend. I like when the most recent is on the top.
I need a trigger to signal to the user that they’ve maxed out The abilities of the free functionality and should register to get access to all the features including editing, sorting, unlimited items, and the ability to access across devices. I could use a simple flash message I could have just some simple paragraph text or this might be a good opportunity to have a full screen modal.
This took me a while to implement which is the signal that I need to just keep iterating over the build to improve the skills and reduce the time it takes.
console.log(window)
console.log(Object.values(book1))
console.log(Object.keys(book1))
ES5 constructors help prevent you from having to manually create copies of object literals
function Book() {
this.title = title;
this.author = author;
this.year = year;
console.log("Book Initialized…")
}
const book1 = new Book()
When you instantiate an object from the constructor it will run whatever is in there. You can add a function as a property.
this.getSummary = function() {
console.log("getSummary from constructor just ran")
}
We can call the getSummary function even if we had 1,000 books. But we don’t need to store it on the constructor itself. Instead we can store it on the prototype so you still have access but is not taking space in the object itself. You may not want getSummary for every book.
Book.prototype.getSummary = function() {
console.log("getSummary as prototype just ran")
}
static methods are where you can have methods in your class that you can use without instantiating an object.
static topBookStore() {
console.log("Barnes and Noble")
}
//Causes Error
book1.topBookStore()
// Get Expected Behavior
Book.topBookStore()