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.
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.
3.137.176.166