Skip to content

04 Add Tasks to the List

Dave Strus edited this page Mar 13, 2015 · 15 revisions

Add Tasks to the List

We need to wire up our form to add items to the task list.

"If you wish to make an apple pie from scratch, you must first invent the universe."

Listen to your friend Carl Sagan. He's a cool dude.

To setup an event handler on a form, you must first have the form. The jQuery function, usually invoked as the $ function, gets elements from the DOM. It accepts a CSS-style selector and returns all matches1, much like document.querySelectorAll.2

jQuery's implementation has a number of differences. Most significant is that what it returns is not simply an array of DOM elements; it's a special array-like collection of jQuery objects that contain the actual DOM elements. Wrapping them in jQuery objects allows us to call an assortment of jQuery functions to traverse and manipulate them. We can also call these functions on the collection itself, and they will be applied to all elements in the collection.

In this case, we have only one element to grab: The form.

$('form#new_task')

To handle the form submission, we set up an onclick event handler. We do this rather than adding an onclick event handler to the submit button, because it works with other means of submitting the form as well (such as pressing the enter key).

In jQuery, we can add event handlers by calling the on method of a jQuery collection or object.

.on( events [, selector ] [, data ], handler )

For now, we'll ignore the optional selector and data parameters. We need to pass it a string naming the event we're handling (submit), and a function to act as the handler. We can pass it in as an anonymous function, or as a reference to a named function.

For now, pass it as an anonymous function. As with traditional event handlers, it will receive an event as an argument, but this time it's jQuery's normalized Event object that deals with some cross-platform inconsistencies for us.

Attach the event handler after our variable and property declarations in the Listly function. As usual with submit handlers, we want to prevent the default behavior. The jQuery Event object includes the familiar preventDefault function.

js/listly.js

    6     self.tasks = [];
    7
    8     $('form#new_task').on('submit', function(ev) {
    9       ev.preventDefault();
   10     });

Ultimately our event handler will do a few things. For now, let's just add a new list item (<li>) to the task list in the DOM. First, we need to get the value of the text field. Use a debugger to see what value this holds in our event handler, since are in jQuery territory.

js/listly.js

    6     self.tasks = [];
    7
    8     $('form#new_task').on('submit', function(ev) {
    9       ev.preventDefault();
   10       debugger;
   11     });

Inspect this in the console, and you'll find that this is set to the actual form element, not a jQueryized version. So we can use traditional DOM properties to get the text field value.

Don't forget to remove the debugger line from your code!

var task_name = this.task_name.value;

If we want to get fully onboard the jQuery train, jQuery objects have a val() function that will give us what we want. We can simply wrap $this.task_name in the $ function and call val().

var task_name = $(this.task_name).val();

Do it whichever way you prefer. In my code snippets here, I'm going to use the jQuery function for consistency's sake.

js/listly.js

    8     $('form#new_task').on('submit', function(ev) {
    9       ev.preventDefault();
   10       var task_name = $(this.task_name).val();
   11     });

jQuery includes several handy functions for adding elements to the DOM. One that fits our needs in this case is append.

.append( content [, content ] )

The append function adds content, specified by the parameter we pass, at the end of the matched elements. (By matched elements, we mean whatever elements are contained in the jQuery object on which we call the function.)

Notice that it can accept multiple parameters. We can include as many pieces of content as we like, and jQuery will append them all.

One of the best things about this and many other DOM-related functions in jQuery is that it accepts a variety of formats for its parameter(s). We can pass in an actual DOM element to be appended; we can pass in an element or elements wrapped in a jQuery object; or we can pass in a string of HTML.

It's very easy for us to build an html string for the <li> that includes our task name.

'<li class="list-group-item">' + task_name + '</li>'

Append that string to the <ol>, which we gave an id of tasks.

js/listly.js

    8     $('form#new_task').on('submit', function(ev) {
    9       ev.preventDefault();
   10       var task_name = $(this.task_name).val();
   11
   12       $('#tasks').append('<li class="list-group-item">' + task_name + '</li>');
   13     });

Try it out in your browser!

It works, but the user experience could be improved. Focus the cursor back inside the text field and clear its value. jQuery's val function can not only get the value of a field, but also set it. We can also call jQuery's focus function to place the cursor back inside the text field.

js/listly.js

    8     $('form#new_task').on('submit', function(ev) {
    9       ev.preventDefault();
   10       var task_name = $(this.task_name).val();
   11
   12       $('#tasks').append('<li class="list-group-item">' + task_name + '</li>');
   13       $(this.task_name).val('');
   14       $(this.task_name).focus();
   15     });

These jQuery functions also return the jQuery object that they act upon, so we can chain the function calls.

js/listly.js

    8     $('form#new_task').on('submit', function(ev) {
    9       ev.preventDefault();
   10       var task_name = $(this.task_name).val();
   11
   12       $('#tasks').append('<li class="list-group-item">' + task_name + '</li>');
   13       $(this.task_name).val('').focus();
   14     });

Try it out.

All told, your JavaScript should now look something like this:

js/listly.js

    1 function Listly() {
    2
    3   function Listly() {
    4     var self = this;
    5
    6     self.tasks = [];
    7
    8     $('form#new_task').on('submit', function(ev) {
    9       ev.preventDefault();
   10       var task_name = $(this.task_name).val();
   11
   12       $('#tasks').append('<li class="list-group-item">' + task_name + '</li>');
   13       $(this.task_name).val('').focus();
   14     });
   15   }
   16  
   17   return Listly;
   18 }
   19 
   20 var listly = new Listly();

1 It can also accept a string of HTML and build a DOM element from it!

2 When jQuery first arrived on the scene, querySelectorAll didn't yet exist, and the jQuery 1.x branch continues to support browsers that lack the built-in function.