官术网_书友最值得收藏!

Time for action – implementing the bindings

Let's head back over to the task template in our HTML file and add some custom data attributes. We'll add custom attributes to all of the task details <input> and <select> elements. The data attribute name will be data-field, and the attribute value will be the name of the field the element matches to in the Task object. We will use those attributes later in our JavaScript to hook the DOM elements and data model together:

<div class="details">
    <label>Start date:</label>
    <input type="date" data-field="startDate"/><br/>
    <label>Due date:</label>
    <input type="date" data-field="dueDate"/><br/>
    <label>Status:</label>
    <select data-field="status">
        <!— options removed... -->
    </select><br/>
    <label>Priority:</label>
    <select data-field="priority">
        <!— options removed... -->
    </select><br/>
    <label>%&nbsp;Complete:</label>
    <input type="number" data-field="pctComplete"
        min="0" max="100" step="10" value="0"/>
</div>

Now that we have a data model, we need to go into the TaskAtHandApp object in taskAtHand.js and update it to use that model. First we'll add a taskList variable and initialize it to an instance of a TaskList object:

function TaskAtHandApp()
{
    var version = "v3.2",
        appStorage = new AppStorage("taskAtHand"),
 taskList = new TaskList();

Then we'll go into the addTask() method and add code to create a new Task object, and add it to the task list. This is also where we save the nextTaskId value into localStorage after it's been incremented:

function addTask()
{
    var taskName = $("#new-task-name").val();
    if (taskName)
    {
 var task = new Task(taskName);
 taskList.addTask(task);
 appStorage.setValue("nextTaskId", Task.nextTaskId);
        addTaskElement(task);
        saveTaskList();
        // Reset the field
        $("#new-task-name").val("").focus();
    }
}

Notice that we also changed the parameter of the addTaskElement() method to pass in the Task object. So let's update the addTaskElement() method to take a Task object as the parameter instead of a task name:

function addTaskElement(task)
{
    var $task = $("#task-template .task").clone();
 $task.data("task-id", task.id);
    $("span.task-name", $task).text(task.name);

After creating a new task element in the DOM we set the task ID on it using a custom data attribute named task-id. This is done with the jQuery data() method that takes the data attribute name and value as parameters. Next we set the task name into the <span> attribute from the task.name field.

Now we will implement the first part of the data binding. This next block of code uses the data attributes we previously added to the markup to set the values from the Task object into the associated <input> and <select> elements in the details section:

    // Populate all of the details fields
    $(".details input, .details select", $task).each(function() {
        var $input = $(this);
        var fieldName = $input.data("field");
        $input.val(task[fieldName]);
    });

Here's how it works:

  1. First it finds all <input> and <select> elements inside the task element.
  2. Then it calls the jQuery each() method, which is used to iterate over the set of selected elements, passing in a callback function.
  3. Inside the callback function this points to the current element. So first we wrap the element in a jQuery object.
  4. Then we use the data() method to get the value of the data-field custom attribute, which is the name of the field in the Task object associated with the element.
  5. Finally we set the value of the user control to the value of the field in the Task object. We get the value from the Task object using square brackets. Remember that in JavaScript object["field"] is the .same as object.field.
    Note

    You can think of using square brackets to access object fields as similar to using reflection in C# or Java to dynamically access values in objects at runtime.

Now we need to add code to go the other way. Whenever the user changes the value of a form control we want to automatically save it back to the data model. So let's add a change event handler for each of the details form controls:

$(".details input, .details select", $task).change(function() {
    onChangeTaskDetails(task.id, $(this));
});

This calls the onChangeTaskDetails() method, passing in the task ID and the form control element that changed wrapped in a jQuery object. Let's implement that method:

function onChangeTaskDetails(taskId, $input)
{
    var task = taskList.getTask(taskId)
    if (task)
    {
        var fieldName = $input.data("field");
        task[fieldName] = $input.val();
        saveTaskList();
    }
}

Let's break it down to see how it works:

  1. First it gets the Task object from the task list with the specified ID.
  2. After making sure we got an object back (you never know, so always check) we get the Task object field name from the element's data-field attribute.
  3. Then we set the value of the field on the Task object to the value of the form control element, again using square brackets to access it dynamically.
  4. Finally we call saveTaskList() to commit the change to localStorage.

That reminds me, we need to rewrite the saveTaskList() method to save our new TaskList object. That's easy enough. We just call the getTasks() method of the task list to get the array of Task objects. Then we save the array to localStorage:

function saveTaskList()
{
    appStorage.setValue("taskList", taskList.getTasks());
}
Note

If you have old task list data from the previous examples you will need to delete it before using the new data model. In Chrome developer tools you can click on the item and press the Delete key to remove it.

What just happened?

First we created a data model to hold all of the task data. Then we added data binding to our application using custom data attributes to automatically update the data model when a field on the page changes. Then we saved the task list to local storage.

主站蜘蛛池模板: 海晏县| 玉门市| 仁怀市| 郴州市| 奇台县| 库尔勒市| 静乐县| 青冈县| 庆云县| 东方市| 信丰县| 视频| 新巴尔虎左旗| 红河县| 云阳县| 田阳县| 漠河县| 马尔康县| 镇沅| 商都县| 泰和县| 色达县| 余干县| 佛山市| 容城县| 五寨县| 米易县| 岗巴县| 银川市| 区。| 钦州市| 洛川县| 宜阳县| 灵寿县| 临沧市| 金山区| 句容市| 峨边| 邓州市| 扶绥县| 平凉市|