6. Step 6 - Implement the Update Use Case

Also for the Update use case, we have an HTML page for the user interface (updateBook.html) and a view code file (src/v/updateBook.js). The HTML form for the UI of the "update book" operation has a selection field for choosing the book to be updated, an output field for the standard identifier attribute isbn, and an input field for each attribute of the Book class that can be updated. Notice that by using an output field for the standard identifier attribute, we do not allow changing the standard identifier of an existing object.

<main>
 <form id="Book">
  <div><label>Select book: 
    <select name="selectBook">
     <option value=""> --- </option></select>
  </label></div>
  <div><label>ISBN: <output name="isbn"></output></label></div>
  <div><label>Title: <input name="title"/></label></div>
  <div><label>Year: <input name="year"/></label></div>
  <div><button type="button" name="commit">
   Save Changes</button></div>
 </form>
</main>

Notice that we include a kind of empty option element, with a value of "" and a display text of ---, as a default choice in the selectBook selection list element. So, by default, the value of the selectBook form control is empty, requiring the user to choose one of the available options for filling the form.

The setupUserInterface procedure now has to populate the select element's option list by loading the collection of all book objects from the data store and creating an option element for each book object:

pl.v.updateBook = {
  setupUserInterface: function () {
    const formEl = document.forms["Book"],
        saveButton = formEl.commit,
        selectBookEl = formEl.selectBook;
    Book.retrieveAll();  // load all book objects
    // populate the selection list with books
    for (const key of Object.keys( Book.instances)) {
      const book = Book.instances[key];
      const optionEl = document.createElement("option");
      optionEl.text = book.title;
      optionEl.value = book.isbn;
      selectBookEl.add( optionEl, null);
    }
    // when a book is selected, fill the form with its data
    selectBookEl.addEventListener("change", 
        pl.v.updateBook.handleBookSelectionEvent);
    // set an event handler for the submit/save button
    saveButton.addEventListener("click",
        pl.v.updateBook.handleSaveButtonClickEvent);
    // handle the event when the browser window/tab is closed
    window.addEventListener("beforeunload", Book.saveAll);
  },
  ...
}

A book selection event is caught via a listener for change events on the select element. When a book is selected, the form is filled with its data:

  handleBookSelectionEvent: function () {
    const formEl = document.forms["Book"],
          selectBookEl = formEl.selectBook,
          key = selectBookEl.value;
    if (key) {
      const book = Book.instances[key];
      formEl.isbn.value = book.isbn;
      formEl.title.value = book.title;
      formEl.year.value = book.year;
    } else {
      formEl.reset();
    }
  },

When the save button is activated, a slots record is created from the form field values and used as the argument for calling Book.update:

  handleSaveButtonClickEvent: function () {
    const formEl = document.forms["Book"],
          selectBookEl = formEl.selectBook;
    const slots = { isbn: formEl.isbn.value,
        title: formEl.title.value,
        year: formEl.year.value
    };
    Book.update( slots);
    // update the selection list option element
    selectBookEl.options[selectBookEl.selectedIndex].text = slots.title;
    formEl.reset();
  }
};