-
-
Save ghinda/8442a57f22099bdb2e34 to your computer and use it in GitHub Desktop.
// takes a {} object and returns a FormData object | |
var objectToFormData = function(obj, form, namespace) { | |
var fd = form || new FormData(); | |
var formKey; | |
for(var property in obj) { | |
if(obj.hasOwnProperty(property)) { | |
if(namespace) { | |
formKey = namespace + '[' + property + ']'; | |
} else { | |
formKey = property; | |
} | |
// if the property is an object, but not a File, | |
// use recursivity. | |
if(typeof obj[property] === 'object' && !(obj[property] instanceof File)) { | |
objectToFormData(obj[property], fd, property); | |
} else { | |
// if it's a string or a File object | |
fd.append(formKey, obj[property]); | |
} | |
} | |
} | |
return fd; | |
}; | |
// usage example | |
var z = objectToFormData({ | |
obj: { | |
prop: 'property value' | |
}, | |
arr: [ | |
'one', | |
'two', | |
'three', | |
new File([''], '') | |
], | |
file: new File([''], '') | |
}); | |
var xhr = new XMLHttpRequest; | |
xhr.open('POST', '/', true); | |
xhr.send(z); | |
// usage for Angular.js | |
// wrap object to formdata method, | |
// to use it as a transform with angular's http. | |
var formDataTransform = function(data, headersGetter) { | |
// we need to set Content-Type to undefined, | |
// to make the browser set it to multipart/form-data | |
// and fill in the correct *boundary*. | |
// setting Content-Type to multipart/form-data manually | |
// will fail to fill in the boundary parameter of the request. | |
headersGetter()['Content-Type'] = undefined; | |
return objectToFormData(data); | |
}; | |
$http({ | |
method: 'POST', | |
url: '/', | |
transformRequest: formDataTransform, | |
data: { your_object: {} } | |
}) | |
.success(function(res) {}); |
Nice piece of code but it doesn't work for all scenarios. What about the following object?
{
"id": 21,
"displayName": "User",
"email": "[email protected]",
"firstName": "First name",
"lastName": "Last name",
"isActive": true,
"createdBy": 52,
"creationDate": "2018-07-23T11:45:15.77",
"note": "",
"profileId": 2,
"userName": "username",
"sendConfirmationEmail": false,
"selectedRoles": [
{ "id": 7, "name": "Administrator", "selected": false },
{ "id": 1, "name": "Entry clerk", "selected": true },
{ "id": 2, "name": "Data entry supervisor", "selected": false }
],
"moduleId": null,
"competencies": [48, 44, 6],
"originalCompetencies": [],
"jobTitle": null,
"departmentName": null,
"selectedModuleId": 0,
"fullName": "Full user name"
}
On the other hand, this code from an answer on SO does the job:
function buildFormData(formData, data, parentKey) {
if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof File) && !(data instanceof Blob)) {
Object.keys(data).forEach(key => {
buildFormData(formData, data[key], parentKey ? `${parentKey}[${key}]` : key);
});
} else {
const value = data == null ? '' : data;
formData.append(parentKey, value);
}
}
I have an array of object.In every single object, I have to pass image file for that object.
let myArray = [
{
"link" : "First link",
image : // Image file
},
{
"link" : "Second link",
image : // Image file
}
]
How can I append this array in formData ?
I have an array of object.In every single object, I have to pass image file for that object.
let myArray = [
{
"link" : "First link",
image : // Image file
},
{
"link" : "Second link",
image : // Image file
}
]How can I append this array in formData ?
Use the function function buildFormData(formData, data, parentKey) {...}
like so:
const formData = new FormData();
buildFormData(formData, myArray);
// use myArray
Hi,
I figured out that the script removes all properties with null value. Why? Because typeof null is object so you get in the recursive loop and then null value will disappear. What do you think about checking obj[property] !== null
?
let fd = form || new FormData();
let formKey;
for (let property in obj) {
if (obj.hasOwnProperty(property)) {
if (namespace) {
formKey = namespace + "[" + property + "]";
} else {
formKey = property;
}
if (
typeof obj[property] === "object" &&
!(obj[property] instanceof File) &&
obj[property] !== null
) {
this.objectToFormData(obj[property], fd, property);
} else {
if (obj[property] !== false) {
fd.append(formKey, obj[property]);
}
}
}
}
return fd;
Namespace is lost. This could fix it:
objectToFormData(obj[property], fd, namespace+"["+ property+"]");
Update for Typescript 2022.
Edit: Date support removed.
function parseGenericObject<T>(
object: T,
form?: FormData,
namespace?: string
): FormData {
const formData = form || new FormData()
for (const property in object) {
const isPropertyExist = property in object
if (!isPropertyExist) {
continue
}
const contextProperty = object[property]
const formKey = namespace ? `${namespace}[${property}]` : property
if (
typeof contextProperty === 'object' &&
!(contextProperty instanceof File)
) {
parseGenericObject<any>(contextProperty, formData, formKey)
} else {
formData.append(formKey, String(contextProperty))
}
}
return formData
}
This does not work. It obviously is not nesting anything.
The server receives: {'p1[p1]' (all one key): val}
instead of {'p1': {'p2': val}}
You know what I did? I just sent the data as a String and I received it as a Json example
Client Side
let ageGroupTarget= { age: { minAge: this.myForm.get('minAge').value, maxAge: this.myForm.get('maxAge').value } }
server Side
JSON.parse(req.body.targetFollowers);