2013-02-07 14 views
12

Czy istnieje sposób użycia Backbone.js i jego architektury modelu do wysłania obiektu formularza do serwera? Problemem, który napotykam, jest to, że wszystko, co wysyła Backbone, jest zakodowane jako JSON, więc obiekt formdata nie jest poprawnie wysyłany (oczywiście).Backbone.js i FormData

Tymczasowo pracuję nad tym, wykonując proste żądanie ajax jQuery i włączając obiekt formdata jako właściwość danych, ale jest to mniej niż idealne.

+0

można zastąpić [ 'sync'] (http://backbonejs.org/#Sync) globalnie, per-modelu, lub per-kolekcji rozmawiać z serwera dowolny sposób. –

+0

Hej, twoja sugestia była podejściem, z którym poszedłem. Możesz to zgłosić jako odpowiedź, a ja to zatwierdzę. – Leonidas

Odpowiedz

7

Wystarczy dodać odpowiedź na to pytanie, herezje jak poszedłem o niej bez konieczności zastąpić sync:

Moim zdaniem mam somethign jak:

$('#' + $(e.currentTarget).data('fileTarget')).trigger('click').unbind('change').bind('change', function(){ 
    var form_data = new FormData(); 
    form_data.append('file', $(this)[0].files[0]); 
    appManager.trigger('user:picture:change', form_data); 
}); 

Który następnie uruchamia funkcja w kontrolerze, który to robi:

var picture_entity = new appManager.Entities.ProfilePicture(); 
picture_entity.save(null, { 
    data: data, 
    contentType: false, 
    processData: false, 
}); 

w tym momencie jestem nadrzędnymi jQuery data z moim FormData obiekt.

7

Miałem podobny wymóg i oto co zrobiłem:

W Widok:

var HomeView = Backbone.View.extend({ 
    el: "#template_loader", 
    initialize: function() { 
     console.log('Home View Initialized'); 
    }, 
    render: function() { 
     var inputData = { 
      cId: cId, 
      latitude: latitude, 
      longitude: longitude 
     }; 

     var data = new FormData(); 

     data.append('data', JSON.stringify(inputData)); 

     that.model.save(data, { 
      data: data, 
      processData: false, 
      cache: false, 
      contentType: false, 
      success: function (model, result) { 
       alert("Success"); 
      }, 
      error: function() { 
       alert("Error"); 
      } 
     }); 
    } 
});  

Nadzieja to pomaga.

16

Oto rozwiązanie, zastępując metodę sync, której używam, aby umożliwić przesyłanie plików.

W tym przypadku zastępuję metodę modelu sync, ale może to być również metoda Backbone.sync.

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:

Aby śledzić postęp przesyłania, można dodać opcję xhr do opcji:

... 

_.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; 
    } 
}); 

... 
+2

To jest dobra odpowiedź, IMO najlepsze na tej stronie. Prawidłowy sposób obsługi komunikacji z serwerem polega na edycji metody synchronizacji, tutaj na poziomie modelu, ale * nie * wymaga obszernego patchowania małp: po prostu edytuj hash opcji (trzymanie danych i opcji xhr) i gotowe. – chikamichi

2

miałem ten sam problem. Powyżej sposób, w jaki go rozwiązuję.

var $form = $("myFormSelector"); 

//==> GET MODEL FROM FORM 
var model = new MyBackboneModel(); 
var myData = null; 
var ajaxOptions = {}; 
// Check if it is a multipart request. 
if ($form.hasFile()) { 
    myData = new FormData($form[0]); 
    ajaxOptions = { 
     type: "POST", 
     data: myData, 
     processData: false, 
     cache: false, 
     contentType: false 
    }; 
} else { 
    myData = $form.serializeObject(); 
} 

// Save the model. 
model.save(myData, $.extend({}, ajaxOptions, { 
    success: function(model, data, response) { 
     //==> INSERT SUCCESS 
    }, 
    error: function(model, response) { 
     //==> INSERT ERROR 
    } 
})); 

Plik hasFile jest niestandardową metodą rozszerzającą funkcje JQuery.

$.fn.hasFile = function() { 
    if ($.type(this) === "undefined") 
     return false; 

    var hasFile = false; 
    $.each($(this).find(":file"), function(key, input) { 
     if ($(input).val().length > 0) { 
      hasFile = true; 
     } 
    }); 

    return hasFile; 
}; 
2

Wystarczy użyć Backbone.emulateJSON = true;: http://backbonejs.org/#Sync-emulateJSON

spowoduje JSON być szeregowane pod parametrem modelu, a wniosek należy dokonać z typem MIME application/x-www-form-urlencoded, jak gdyby z formularza HTML.

+0

Ale to serializuje JSON do napisu i pojawia się jako obiekt typu string. –

+0

Tworzy obiekt formData i wysyła go na serwer –

1

Żadna z odpowiedzi nie zadziałała, poniżej jest proste i łatwe rozwiązanie. Nadrzędnymi sync sposób i options.contentType takiego:

sync: function(method, model, options) { 
    options = _.extend({ 
     contentType : 'application/x-www-form-urlencoded;charset=UTF-8' 
    }, options); 

    options.data = jQuery.param(model.toJSON()); 

    return Backbone.sync.call(this, method, model, options); 
} 
0

prosta będzie, mam nadzieję, że to pomoże ktoś.

  1. Tworzenie obiektu szkieletu modelu

    var importModel = new ImportModel(); 
    
  2. połączeń Zapisz [post] metodę Backbone modelu i przekazać obiekt FormData.

    var objFormData = new FormData(); 
    objFormData.append('userfile', files[0]); 
    
    importModel.save(objFormData, { 
    contentType: false, 
    data: objFormData, 
    processData: false, 
    success: function(data, status, xhr) { }, 
    error: function(xhr, statusStr) { } 
    });