Page 2

Adding a Note

If you haven’t already, check out the demo to get a feel for what we’ll be building. In this page, we’ll walk through adding a Note starting with the user’s mouse-click in the View, and walk all the way through a successful and unsuccessful AJAX response.

Overview

(graphic of organization here. show arrows for listeners, and the fork response from the Model depending on AJAX status.

The Process

To start the process, the user fills out the add form and clicks on the [Add Note] button: what happens? Let’s start by looking at the .click() listener that’s attached to the add button, taking special note of line 108:

// the user wants to add a new Note
// so validate the form, and then
// add a new Note
function submitAddForm(){
    var subj = $addform.find(".subject").val();
    var body = $addform.find(".body").val();
    if(subj.length == 0){
        alert("Please enter a subject for your note");
    }else{
        that.notifyNewNote(subj, body);
    }
    return false;
}
$addform.submit(submitAddForm);
$addform.find("#add").click(submitAddForm);

After some simple client-side validation, we call notifyNewNote() with the subject and body for the new Note. The notifyNewNote() function works just like our notify() functions from Phase 1, so I won’t rehash that here. Next, let’s take a look at what the Controller hears with its listener:

var vlist = $.ViewListener({
    deleteNoteClicked : function(note_id){
        model.deleteNote(note_id);
    },
    newNoteClicked : function(subj, body){
        model.addNote(subj, body);
    }
});
view.addListener(vlist);

Simple enough! On line 12 we see the Controller just tells the Model to add the Note. So far, all we’ve done is validate the user’s input, and tell the Model to add the note, now let’s see what happens from the Model’s perspective.

this.addNote = function(subj, body){
    that.notifyAddingNote();
    $.ajax({
        url: 'ajax.php',
        data : { add : true, 
                 subject : subj,
                 body : body },
        type: 'POST',
        dataType: 'json',
        timeout: 1000,
        error: function(){
            that.notifyAddingFailed();
        },
        success: function(data){
            if(data.error) return that.notifyAddingFailed();
            that.notifyAddingFinished(loadResponse(data));
        }
    });
    return cache.toArray();
}

Taking a close look at this function, we’ll see that it will fire three notifications to it’s listeners: 1 to notifyAddingNote(), 1 to either notifyAddingFailed() or notifyAddingFinished(), and 1 to notifyLoadNote() (called from inside loadResponse()). In fact, the model is probably the class that will have the most notify() functions. It’s good practice to notify before an AJAX call, again while processing the JSON response, and one last time after everything completes.

You can see this in action in the demo – just fill in the form and click [Add Note], and the console should show 3 lines:

adding new note...
loading single: 44
just added via ajax: 44

So where are those console lines actually printed? We haven’t seen any code that logs to the View’s console yet. For that, let’s look at what the Controller hears when it listens to the Model’s 3 notifications. Below is a snippet of the Controller’s $.ModelListener() that’s been added to the Model.

loadNote : function(note){
    view.log("loading single: " + note.getId());
    view.loadNote(note);
},
addingNote : function() {
    view.log("adding new note...");
    view.setAddFormEnabled(false);
},
addingFailed : function() {
    view.log("adding new note failed");
    alert("failed adding note");
    view.setAddFormEnabled(true);
},
addingFinished : function(newNotes) {
    $.each(newNotes, function(i){
        view.log("just added via ajax: " + newNotes[i].getId());
    });
    view.setAddFormEnabled(true);
    view.clearAddForm();
},

Ah ha! Here we finally see the explicit logs to the View’s console, as well as updates to the View’s state. It’s the Controller where the real magic happens. The View and Model just deal with the end points, it’s the Controller that ties these things together – nice and neat.

I won’t dive deeper into the guts of what setAddFormEnabled() and clearAddForm() etc actually do – I’m guessing you can guess from the names 😉 but take special note of the loadNote() function: the Controller passes the Note object straight on over to the View. This is going to be important as we take a look at editing a note on the next page. I also won’t go over how deleting a note works, since the process and code is nearly identical to adding a note.

Summary

Where Phase 1 failed us – using MVC in a real application – this phase is beginning to fill in. Now we see that even as the  application grows in complexity, the View can manage exactly and only code that’s specific to the View, and the Model can manage exactly and only code that deals with AJAXing and caching data, and it’s the Controller where are real application logic happens.

And it’s only natural, right? User interfaces are naturally event driven. The user clicks, drags, types, deletes, clicks again. AJAX is naturally event driven and asynchronous. What this MVC let’s us do is contain each of these categories of events in their own classes: the View manages user events, the Model manages AJAX events, and the Controller sits between these two and helps tie these events together in a meaningful way.

Next, we’ll take a look at the process for editing Notes.

Leave a Reply

Your email address will not be published. Required fields are marked *