Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adapt my old work flow to Backbone

Im starting to build a new app and I would like to use Backbone as my framework. Below is a basic workflow that this (and most apps) follow.

What is the correct/best model to use with Backbone?

Old Way
User navigates to a page.
Selects "Create New widget"
User is presented with a form filled with inputs
At this point I would probably take the values entered (after passing basic validation), wrap them up and send them to the server via an ajax request
Request comes back as "OK" and the user is taken somewhere else (This step isn't entirely important)

Some basic pseudo-code

// Grab values
var userName = $('.UserName').val(),  
    dateOfBirth = $('.DateOfBirth').val();  
  ...  
  ...   
  ...

 $.ajax({
  url: "/Webservices/ProcessStuff",
  success: function(result){
   if (result) { 
    // Render something or doing something else
   } else {
    // Error message
   }
  },
  error: function () { 
    // Error message
  }
});

Backbone way
Using the same example as above; I assume I'd have a model for the user information and a view to display the inputs. However, processing the actual call to the web service is one of the things I'm confused about. Where does this need to go? In the model or in the view click of some "Go" button?

Model.UserInformation = Backbone.Model.extend({ username: null, dateOfBirth: null });

Maybe also have a collection of these UserInformation models?
UserInformations = Backbone.Collection.extend({ model: Model.UserInformation' });

So bottom line what I'm asking is...
What is the best way to achieve this functionality?
What is the proper way to actually perform CRUD? Where to put the actual call to delete/update/create/etc?

like image 339
Mike Fielden Avatar asked Oct 10 '11 16:10

Mike Fielden


1 Answers

You have the right idea and Backbone should make it easy for you to get things done using the same basic high level overview of your workflow. Note that you're still going to be using jQuery for this functionality - you'll just be doing it through the organizational aspects of Backbone's types.

There are a couple of key items that you'll want in place, most of which you already mentioned:

  • A backbone View to coordinate the HTML elements with your Javascript code
  • A backbone Model to store all of the data that the user input into the HTML elements
  • A back-end server that can handle RESTful JSON calls via AJAX requests from jQuery

I think the only thing you are missing is that the model has a save method on it, which wraps up all of the logic to call the create / update routes on your back-end server. The model also has a delete method to handle deletion from the server.

As a very simple example, here's a form that renders an HTML template to the screen, gathers the user input in to the model and then saves it to the server.

An HTML template:


<script id="myTemplate" type="text/x-jquery-tmpl">
  First name: <input id="first_name"><br/>
  Last Name: <input id="last_name"><br/>
  <button id="save">Save!</button>
</script>  

The code to run this:


MyModel = Backbone.Model.extend({
  urlRoot: "/myModel"
});

MyView = Backbone.View.extend({
  template: "#myTemplate",

  events: {
    "change #first_name": "setFirstName",
    "change #last_name: "setLastName",
    "click #save": "save"
  },

  initialize: function(){
    _.bindAll(this, "saveSuccess", "saveError");
  },

  setFirstName: function(e){
    var val = $(e.currentTarget).val();
    this.model.set({first_name: val});
  },

  setLastName: function(e){
    var val = $(e.currentTarget).val();
    this.model.set({last_name: val});
  },

  save: function(e){
    e.preventDefault(); // prevent the button click from posting back to the server
    this.model.save(null, {success: this.saveSuccess, error: this.saveError);
  },

  saveSuccess: function(model, response){
    // do things here after a successful save to the server
  },

  saveError: function(model, response){
    // do things here after a failed save to the server
  },

  render: function(){
    var html = $(this.template).tmpl();
    $(el).html(html);
  }
});

myModel = new MyModel();
myView = new MyView({model: myModel});
myView.render();
$("#someDivOnMyPage").html(myView.el);

This will give you a quick start for a form that saves a new model back to the server.

There are a couple of things your server needs to do:

  • Return a valid HTTP response code (200 or some other response that says everything was "ok")
  • Return the JSON that was sent to the server, including any data that the server assigned to the model such as an id field.

It's very important that your server do these things and include an id field in the response. Without an id field from the server, your model will never be able to update itself when you call save again. It will only try to create a new instance on the server again.

Backbone uses the id attribute of a model to determine if it should create or update a model when pushing data to the back end. The difference between creating a new model and saving one is only the id attribute. You call save on the model whether it's a new or an edited model.

A delete works the same way - you just call destroy on the model and it does a call back to the server to do the destroy. With some HTML that has a "delete" link or button, you would attach to the click event of that HTML element the same as I've shown for the "Save" button. Then in the callback method for the delete click, you would call this.model.destroy() and pass any parameters you want, such as success and error callbacks.

Note that I included a urlRoot on the model, as well. This, or a url function are needed on a model if the model is not part of a collection. If the model is part of a collection, the collection must specify the url.

I hope that helps.

like image 190
Derick Bailey Avatar answered Nov 18 '22 11:11

Derick Bailey