The way we program is always evolving, and Web apps are no exception. The surge in mobile-app development (iOS and Android) has reminded programmers about the beauty of pretty, well-funded commercial APIs. Developing apps for the Web can be extra frustrating, comparatively, due to limited functionality and differences in Web browsers and slow-evolving “standards” that define functionality. Desktop apps tend to be much faster than Web apps because they operate “close to the user” — on his CPU. Web apps are different from Desktop apps because much of their processing happens at a remote location — the server. There is an exception — the front-end of a Web app (JavaScript) runs “close to the user” — on his CPU.

One of the really beautiful things about developing apps for the Desktop (or mobile) is the “MVC pattern”. Ruby on Rails and other Web app frameworks have popularized a type of MVC for the Web called “Model 2”, but it’s not good enough. With Model 2 Web apps, the user waits while the server combines templates with data and sends the output to the Web browser.

Web apps can be a lot better than that. If you haven’t built an app with Backbone.js or Spine.js yet — you’re in for a treat. Backbone and Spine are “client-side MVC” frameworks for the JavaScript portion of your Web apps. By putting a Model (description and storage of your app’s data) in the client, they make it possible to show the user his data immediately after he manipulates it. This makes a huge difference to the perceived speed of an app.

In the background, the Model syncs its data with server-side storage. Backbone and Spine make it easy to store your app’s data in HTML5 LocalStorage or using Ajax to sync with a HTTP API on the server.

Here’s an example client-side MVC app, written in Spine (and supported on the back-end by Structal, a server-side HTTP app I wrote).

The two main parts of your Spine app are its Model and Controller. The Model is a description of the classes of data in your app and the specific field names in your data storage. The Controller is a piece of code that hooks to and captures events from the user interface and Model.

Creating a Spine Model for the “posts” collection:

var Post = Spine.Model.sub();

Post.configure( 'Post', 'author', 'title' );

The Model describes a single Post, in the collection of posts in our new blogging app. The first line creates a Model in a variable called Post, which is a subclass of Spine.Model. The second line fires the Post Model’s configure method, and tells it that the Model is called “Post” and it has two fields in storage named “author” and “title”.

Spine and Backbone are different in little ways, they are both terrific. I picked Spine for this tutorial because it feels a little more fun to use. Backbone has a much larger community and a much more stable API.

Now that we have a Model, we need to tell it how to store its data. We’ll extend the Post Model with Ajax, which tells Spine to save all of that Model’s data to a remote server using GET, PUT, POST and DELETE. I’m tempted to say something about Restful URLs here (Spine and Backbone use the same URLs) but after following Roy Fielding’s blog I’ve learned that most of what we have all been thinking was Restful was really not at all.

Post.extend( Spine.Model.Ajax );

This line of code tells Spine to store the Post Model’s data on the server, not in HTML5 LocalStorage.

That’s all we have to do with the Model — not too bad, eh? The Controller is pretty approachable as well, here’s an example:

Let’s assume that you have some HTML with three elements: an unordered list of posts, an input field for typing the title of a new post, and a button to click to create the post.

<ul class="posts"></ul>

<input type="text" id="title" />

<button class="create">Create Post</button>

Next, you will need to configure your new Controller object and create a few methods on it. Configuration involves specifying the elements and events that the controller is interested in. The elements we want to tell the Controller about are the input field and the list:

var Posts = Spine.Controller.sub({

 elements: { // the elements array

  ".posts": "posts",

  "input[type=text]": "input"

 }

});

Here, we’ve created a Spine Controller by subclassing Spine.Controller. On the Controller, we’ve added an elements array that links parts of our user interface to local references. By doing this, our Controller can refer to this.input instead of $(“input[type=text]) — much cleaner.

init: function() { // the init() method of the Controller

 Post.bind( 'refresh change', this.proxy( this.render )); // hook to the refresh and change events of the model

 Post.fetch(); // do a GET request to the server: /posts

}

The Controller’s init() method is important — this is where the Post model is connected to our Controller. The first line says that Post Model is told to notify the Controller (run its render() method) when data refresh and change events occur (this is where the real difference between Model 2 and MVC come into play — here we are using the “observer pattern” — an essential MVC ingredient mostly missing from Model 2 apps. On the second line, the Post model calls its fetch() method to do a GET to the /posts URL and get JSON back with a list of posts. Calling Post.fetch() will trip the Controller’s render() method, causing the posts to be displayed in the unordered list.

render: function() {// the render() method of the Controller

 posts = Post.all(); // fetch all of the posts from the Model

 for (p in posts) // loop over each post

  this.posts.prepend(Mustache.to_html(tpl,posts[p])); // tpl is some Mustache HTML template data, '<li>{{title}}</li>'

}

Here we have the render() method — which gets triggered by the refresh and change events on the Model. When render() is called, the browser fetches the list of posts from the server by calling the Post Model’s all() method. Then, for each post it uses this.posts (the shortcut to the unordered list, described in the elements array) and calls prepend() to pop a Mustache-rendered list item onto the unordered list.

Adding events to our controller is easy — the following code reads as follows: “connect the ‘click’ event of any elements of class ‘create’ (the button in our HTML) to this Controller’s ‘create’ method” — i.e. when the button is clicked, fire this Controller’s create method.

events: { // the events array

 'click .create': 'create', // hook the click event of the button

}

The create() method calls the Post Model’s create() method, passing it the data for a new post. You can see a reference to this.input — that is the shortcut to the form text input box — defined in the Controller’s elements array).

create: function() { // the create() method of the Controller

 p = Post.create({ author:'', title:this.input.val() }); // create a new post with an author and title

 this.input.val(''); // erase the title from the text box

}

The complete source code to this example can be found on Github.

Categories: Web Apps

Related Posts

Web Apps

Build a real-time microblog w/ajax data model sync

Structal is a new tool that mates the new client-side MVC frameworks (Spine and Backbone) with a back-end that provides automatic ajax data model Sync, and real-time JSON change feeds for each resource (SQL or Read more…