Accomplishing more with JS

The power of JS and the myriad of things you can do with it in front-end development goes well beyond a simple form validation. To get a better taste of JS, let's do a more interesting task and make MyBooksApp front-end a bit useful.

TASK

The goal here is to enhance the authors view by adding a little button labled X next to each author. When the user clicks that button, a post request with author's name is sent to delauthor route on the server to delete that author. Then, the page will be reloaded updaing the front-end to show/confirm that the author was deleted sucessfully from the database.

Let's make it happen! First, make sure you have an active delauthor API endpoint in your server to accept post requests and delete the author from the Authors table based on name query param (i.e. author's name). Then, go to authors.vm and insert the following inside and at the end of the li tag.

<button type="button" class="$author.name">X</button>

So, it should now be:

<li class="content author"><i>$author.name</i> ($author.nationality) has published $author.numOfBooks books. <button type="button" class="$author.name">X</button></li>

This will add a little X button next to each author.

tip

Note how we use the author's name to set class attribute of each button. This info makes it easy on the front-end side to delete the author whenever a delete button is clicked.

tip

This is not the best idea to set class attribute to author's name, but for the purposes of this example, it should be fine.

Next, head to mybooksapp.css and add the following:

ol li button {
color: red;
border-radius: 50%;
font-weight: bold;
border: 2px solid red;
}

Pay attention to how we set up the selector: it selects all button tags nested inside <li> tags nested inside ol tags. Note this is just one way of selecting the little delete buttons we have added, and you may very well be able to select them in some different way (indicating the flexibility that CSS offers!).

After that, create a file named delauthor.js under the src/resources/public/js folder with the following content:

function deleteAuthor(authorName) {
fetch('http://localhost:7000/delauthor?name=' + authorName, {
method: 'POST',
}
).then(res => window.location.reload(true));
}
let delButtons = document.querySelectorAll("li.author > button")
Array.prototype.forEach.call(delButtons, function(button) {
button.addEventListener('click', deleteAuthor.bind(null, button.className));
});

And finally add <script src="js/delauthor.js"></script> to authors.vm before </body> (i.e. before #parse("public/templates/bottom.vm")).

In the JS code, we first get all the little buttons using querySelectorAll and selecting all button tags nested inside li tags with class name of author. Then, we add an event listener for the click event on each of the buttons so that whenever a delete button is clicked the deleteAuthor function is invoked and the corresponding author name is passed to it. Inside deleteAuthor, we send a post request, using Fetch API to the delauthor route supplying the author name as a query param resulting in removal of the author with that name. Since the sending and processing of the post request can take a bit of time, once the response is ready we reload the page using window.location.reload(true).