ActiveAdmin Form Preview With Javascript FormData

One of my recent tasks has been to build a preview of a form submission into an existing application. Having done something similar in the past involving changing the forms action with javascript, ajax posting the form (including images), generating a preview, changing the form back blaa blaa blaa blaa blaaaaa. I wanted to find a cleaner way to a) deal with the preview and b) ajaxing blob data (image/files) and thanks to not having to support IE implemented the following procedure using FormData and XMLHttpRequest 2.

FormData is awesome, give it a form including blob data and it’ll return an object that can be attached to $.ajax or standard XMLHttpRequest.send and all the caveats and nuiances of ajax forms disappear in the blink of an eye.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// something like
var fd = FormData.new( $('form')[0] );

$.ajax({
  ...
  url: '/iwantdata',
  data: fd,
  ...
})

// or

var ajax = new XMLHttpRequest();
ajax.open("POST", "/iwantdata");
ajax.send(fd));

My stratergy then was simple, take more fieldset, clone it, wrap it in a formtag (all in memory), create the formdata object and away we go images and all. So my first attempt looked as follows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var buildFormData = function($fieldset){
  var $clone = $('#fieldset').clone({ deepWithDataAndEvents: true});
  var $form = $('<form />).append($clone);
  var fd = new FormData($form[0])
  return fd
};

var sendPreview = function(formData){
  $.ajax({
   url: "/iwantdata",
   type: "POST",
   data: formData,
   processData: false,
   contentType: false,
  }).done(weDidIt);
};

This worked great at first all the data was being submitted correctly excpet file fields. These werent being copied over at all due to the caveats of browser security and cloning file fields it seems. So instead of doing it all in memory, which would have been the ideal, I had to use the file fields in the DOM but didnt want to have to pull the form apart and put it back together. Even though the html specification has a big NO NO when it comes to nested form tags it is possible to create them with javascript and this is what i did to build my in place subsection FormData.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var buildFormData = function($fieldset){
  var $form = $fieldset.wrap('<form />').closest('form');
  var fd = new FormData($form[0])
  $fieldset.unwrap();
  return fd
};

var sendPreview = function(formData){
  $.ajax({
   url: "/iwantdata",
   type: "POST",
   data: formData,
   processData: false,
   contentType: false,
  }).done(weDidIt);
};

Not ideal but this solution was a simple way to create a FormData from a subset of fields on the fly which includes all the file field information also.

Comments