Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone.js and FormData

Is there any way using Backbone.js and it's model architecture that I can send a formdata object to the server? The problem I'm running into is that everything Backbone sends is encoded as JSON so the formdata object is not properly sent (obviously).

I'm temporarily working around this by making a straight jQuery ajax request and including the formdata object as the data property, but this is less than ideal.

like image 831
Leonidas Avatar asked Feb 07 '13 04:02

Leonidas


1 Answers

Here is a solution by overriding the sync method, which I use to allow file uploads.

In this case I override the model's sync method, but this can also be the Backbone.sync method.

var FileModel = Backbone.Model.extend({

  urlRoot: CMS_ADMIN_URL + '/config/files',

  sync: function(method, model, options){

    // Post data as FormData object on create to allow file upload
    if(method == 'create'){
      var formData = new FormData();

      // Loop over model attributes and append to formData
      _.each(model.attributes, function(value, key){
        formData.append(key, value);
      });

      // Set processData and contentType to false so data is sent as FormData
      _.defaults(options || (options = {}), {
        data: formData,
        processData: false,
        contentType: false
      });
    }
    return Backbone.sync.call(this, method, model, options);
  }
});

EDIT:

To track upload progress, you can add a xhr option to options:

...

_.defaults(options || (options = {}), {
  data: formData,
  processData: false,
  contentType: false
  xhr: function(){
    // get the native XmlHttpRequest object
    var xhr = $.ajaxSettings.xhr();
    // set the onprogress event handler
    xhr.upload.onprogress = function(event) {
      if (event.lengthComputable) {
        console.log('%d%', (event.loaded / event.total) * 100);
        // Trigger progress event on model for view updates
        model.trigger('progress', (event.loaded / event.total) * 100);
      }
    };
    // set the onload event handler
    xhr.upload.onload = function(){
      console.log('complete');
      model.trigger('progress', 100);
    };
    // return the customized object
    return xhr;
  }
});

...
like image 194
Koen. Avatar answered Sep 29 '22 20:09

Koen.