Skip to content

Commit

Permalink
feat(api): serializeObject, formdata, files
Browse files Browse the repository at this point in the history
This PR implements an optimized version of the original jquery-serializeobject dependency of SUI when serializeForm:true was used.

https://github.com/macek/jquery-serialize-object/blob/master/jquery.serialize-object.js
I enhanced the original logic to also support file inputs, convert pure number values and support same name keys (without trailing [])

I also added support to use The FormData Api when serializeForm is set to 'formdata'. This way the old code stays backward compatible.
  • Loading branch information
lubber-de authored Mar 23, 2022
1 parent f9f3304 commit acc903b
Showing 1 changed file with 68 additions and 13 deletions.
81 changes: 68 additions & 13 deletions src/definitions/behaviors/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -428,28 +428,76 @@ $.api = $.fn.api = function(parameters) {
formData: function(data) {
var
formData = {},
hasOtherData
hasOtherData,
useFormDataApi = settings.serializeForm === 'formdata'
;
data = data || originalData || settings.data;
hasOtherData = $.isPlainObject(data);

$.each($form.serializeArray(), function (i, element) {
var node = formData[element.name];

if ('undefined' !== typeof node && node !== null) {
if (Array.isArray(node)) {
node.push(element.value);
if (useFormDataApi) {
formData = new FormData($form[0]);
settings.processData = typeof settings.processData !== 'undefined' ? settings.processData : false;
settings.contentType = typeof settings.contentType !== 'undefined' ? settings.contentType : false;
} else {
var formArray = $form.serializeArray(),
pushes = {},
pushValues= {},
build = function(base, key, value) {
base[key] = value;
return base;
}
;
// add files
$.each($('input[type="file"]',$form), function(i, tag) {
$.each($(tag)[0].files, function(j, file) {
formArray.push({name:tag.name, value: file});
});
});
$.each(formArray, function(i, el) {
if (!settings.regExp.validate.test(el.name)) return;
var isCheckbox = $('[name="' + el.name + '"]', $form).attr('type') === 'checkbox',
floatValue = parseFloat(el.value),
value = (isCheckbox && el.value === 'on') || el.value === 'true' || (String(floatValue) === el.value ? floatValue : (el.value === 'false' ? false : el.value)),
nameKeys = el.name.match(settings.regExp.key) || [], k, pushKey= el.name.replace(/\[\]$/,'')
;
if(!(pushKey in pushes)) {
pushes[pushKey] = 0;
pushValues[pushKey] = value;
} else if (Array.isArray(pushValues[pushKey])) {
pushValues[pushKey].push(value);
} else {
formData[element.name] = [node, element.value];
pushValues[pushKey] = [pushValues[pushKey] , value];
}
} else {
formData[element.name] = element.value;
}
});
value = pushValues[pushKey];

This comment has been minimized.

Copy link
@lfpommes

lfpommes Oct 23, 2022

HI all, the override of the value at this line, ends up in an issue, when using arrays, e.g. Formdata looks like: "item[][name]=1" "item[][name]=2".
This will result in
{ "item": [
"name": 1
],
[
"name" : [ 1, 2 ]
]
}
The problem is that we


while ((k = nameKeys.pop()) !== undefined) {
// foo[]
if (k == '' && !Array.isArray(value)){
value = build([], pushes[pushKey]++, value);
}
// foo[n]
else if (settings.regExp.fixed.test(k)) {
value = build([], k, value);
}
// foo; foo[bar]
else if (settings.regExp.named.test(k)) {
value = build({}, k, value);
}
}
formData = $.extend(true, formData, value);
});
}

if(hasOtherData) {
module.debug('Extending existing data with form data', data, formData);
data = $.extend(true, {}, data, formData);
if(useFormDataApi) {
$.each(Object.keys(data),function(i, el){
formData.append(el, data[el]);
});
data = formData;
} else {
data = $.extend(true, {}, data, formData);
}
}
else {
module.debug('Adding form data', formData);
Expand Down Expand Up @@ -1088,6 +1136,8 @@ $.api.settings = {
defaultData : true,

// whether to serialize closest form
// use true to convert complex named keys like a[b][1][c][] into a nested object
// use 'formdata' for formdata web api
serializeForm : false,

// how long to wait before request should occur
Expand Down Expand Up @@ -1158,6 +1208,11 @@ $.api.settings = {
regExp : {
required : /\{\$*[A-z0-9]+\}/g,
optional : /\{\/\$*[A-z0-9]+\}/g,
validate: /^[a-z_][a-z0-9_-]*(?:\[(?:\d*|[a-z0-9_-]+)\])*$/i,
key: /[a-z0-9_-]+|(?=\[\])/gi,
push: /^$/,
fixed: /^\d+$/,
named: /^[a-z0-9_-]+$/i
},

className: {
Expand Down

0 comments on commit acc903b

Please sign in to comment.