Creating CheckList Rows on Submit

Next, you will add a method to CheckList that will use the Row constructor to create Row instances. It will append each Row instance’s $element to the live DOM on the page.

In checklist.js, add a method to CheckList.prototype called addRow. It should accept an argument called coffeeOrder, which will be an object that contains all of the data for a single coffee order.

In this new method, create a new Row instance by calling the Row constructor and passing it the coffeeOrder object. Assign the new instance to the variable rowElement. Then, append the rowElement’s $element property (which contains the DOM subtree) to the CheckList instance’s $element property (which is a reference to the container for the checklist items).

...
  function CheckList(selector) {
    ...
  }

  CheckList.prototype.addRow = function (coffeeOrder) {
    // Create a new instance of a row, using the coffee order info
    var rowElement = new Row(coffeeOrder);

    // Add the new row instance's $element property to the checklist
    this.$element.append(rowElement.$element);
  };

  function Row(coffeeOrder) {
    ...

This is all you need to do to add the Row’s DOM subtree to the page. Save checklist.js.

In main.js, add a variable for the selector that matches the entire checklist area, [data-coffee-order="checklist"]. Then, import the CheckList module from the App namespace to a local variable, CHECKLIST_SELECTOR.

(function (window) {
  'use strict';
  var FORM_SELECTOR = '[data-coffee-order="form"]';
  var CHECKLIST_SELECTOR = '[data-coffee-order="checklist"]';
  var App = window.App;
  var Truck = App.Truck;
  var DataStore = App.DataStore;
  var FormHandler = App.FormHandler;
  var CheckList = App.CheckList;
  var myTruck = new Truck('ncc-1701', new DataStore());
...

Now you can instantiate a CheckList instance to add checklist items.

You might be tempted to just add another call to formHandler.addSubmitHandler, but this would not work the way you might expect. Why not? Each time you call addSubmitHandler, it registers a new callback that resets the form (by calling this.reset).

Consider the following code:

...
// Instantiate a new CheckList
var checkList = new CheckList(CHECKLIST_SELECTOR);

var formHandler = new FormHandler(FORM_SELECTOR);
formHandler.addSubmitHandler(myTruck.createOrder.bind(myTruck));

// This will not do what you want!
formHandler.addSubmitHandler(checkList.addRow.bind(checkList));
...

This code registers two callbacks that will run when the form is submitted. After the first submit handler (myTruck.createOrder) is called, the form gets reset. When the second submit handler (checkList.addRow) is called, there is no information left in the form. The result is that the data is added to the DataStore, but a checklist item does not get added to the page.

To get around this, you need to pass a single anonymous function to formHandler.addSubmitHandler and have that anonymous function call both myTruck.createOrder and checkList.addRow.

Also, each of these methods needs to be bound to a specific instance (meaning its this keyword needs to be set). You have been using bind to set the value of this, but you will use a different technique here.

Manipulating this with call

The call method works similarly to bind to set the value of this. The difference between the two is that while bind returns a new version of the function or method, it does not invoke it. call actually invokes the function or method and allows you to pass in the value of this as the first argument. (If you need to pass any other arguments to the function, you just add them to the argument list.) call runs the body of the function and returns any value that would normally be returned.

You need to use call instead of bind here because you need to invoke myTruck.createOrder and checkList.addRow in addition to setting the value of this.

In main.js, remove the existing invocation of formHandler.addSubmitHandler. Add a new call to formHandler.addSubmitHandler and pass it an anonymous function that expects a single argument, data. Inside the anonymous function, use the call methods of myTruck.createOrder and checkList.addRow to set the value of this, passing the data object as the second argument.

...
  var myTruck = new Truck('ncc-1701', new DataStore());
  window.myTruck = myTruck;
  var checkList = new CheckList(CHECKLIST_SELECTOR);
  var formHandler = new FormHandler(FORM_SELECTOR);

  formHandler.addSubmitHandler(myTruck.createOrder.bind(myTruck));
                               function (data) {
    console.log(formHandler);
    myTruck.createOrder.call(myTruck, data);
    checkList.addRow.call(checkList, data);
  });
})(window);

You have created a single submit handler function that invokes both createOrder and addRow. When it invokes them, it passes the correct value of this and the data from the form.

Save your changes and try out your checklist functionality in the browser by entering some data and submitting the form. When you submit each order, you will see it added to the Pending Orders checklist, as in Figure 11.6.

Figure 11.6  Submitting the form adds an item to the checklist

Submitting the form adds an item to the checklist
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.176.166