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

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.

主站蜘蛛池模板: 中超| 乳源| 遂溪县| 会昌县| 原平市| 双城市| 唐河县| 莒南县| 眉山市| 菏泽市| 睢宁县| 武乡县| 肃南| 萍乡市| 新野县| 鄂伦春自治旗| 开平市| 藁城市| 贡觉县| 神农架林区| 新乡市| 长岛县| 墨江| 临夏市| 陆河县| 黑龙江省| 屯门区| 苗栗市| 沙坪坝区| 南宁市| 崇仁县| 大丰市| 秀山| 佛坪县| 光泽县| 靖州| 成都市| 灵寿县| 松滋市| 太保市| 淳安县|