如何将表单的所有元素转换为JavaScript对象?
我希望有某种方法从表单自动构建JavaScript对象,而不必遍历每个元素。我不希望使用$('#formid').serialize();返回的字符串;,我也不希望$('#formid').serializeArray()返回映射;
如何将表单的所有元素转换为JavaScript对象?
我希望有某种方法从表单自动构建JavaScript对象,而不必遍历每个元素。我不希望使用$('#formid').serialize();返回的字符串;,我也不希望$('#formid').serializeArray()返回映射;
当前回答
我的库phery中的代码有一个序列化例程,可以处理非常复杂的表单(如演示中所示https://github.com/pocesar/phery/blob/master/demo.php#L1664),而且不是一刀切。它实际上检查每个字段的类型。例如,单选框与范围不同,与keygen不同,与select multiple不同。我的功能涵盖了这一切,你可以看到它在https://github.com/pocesar/phery/blob/master/phery.js#L1851.
serializeForm:function (opt) {
opt = $.extend({}, opt);
if (typeof opt['disabled'] === 'undefined' || opt['disabled'] === null) {
opt['disabled'] = false;
}
if (typeof opt['all'] === 'undefined' || opt['all'] === null) {
opt['all'] = false;
}
if (typeof opt['empty'] === 'undefined' || opt['empty'] === null) {
opt['empty'] = true;
}
var
$form = $(this),
result = {},
formValues =
$form
.find('input,textarea,select,keygen')
.filter(function () {
var ret = true;
if (!opt['disabled']) {
ret = !this.disabled;
}
return ret && $.trim(this.name);
})
.map(function () {
var
$this = $(this),
radios,
options,
value = null;
if ($this.is('[type="radio"]') || $this.is('[type="checkbox"]')) {
if ($this.is('[type="radio"]')) {
radios = $form.find('[type="radio"][name="' + this.name + '"]');
if (radios.filter('[checked]').size()) {
value = radios.filter('[checked]').val();
}
} else if ($this.prop('checked')) {
value = $this.is('[value]') ? $this.val() : 1;
}
} else if ($this.is('select')) {
options = $this.find('option').filter(':selected');
if ($this.prop('multiple')) {
value = options.map(function () {
return this.value || this.innerHTML;
}).get();
} else {
value = options.val();
}
} else {
value = $this.val();
}
return {
'name':this.name || null,
'value':value
};
}).get();
if (formValues) {
var
i,
value,
name,
$matches,
len,
offset,
j,
fields;
for (i = 0; i < formValues.length; i++) {
name = formValues[i].name;
value = formValues[i].value;
if (!opt['all']) {
if (value === null) {
continue;
}
} else {
if (value === null) {
value = '';
}
}
if (value === '' && !opt['empty']) {
continue;
}
if (!name) {
continue;
}
$matches = name.split(/\[/);
len = $matches.length;
for (j = 1; j < len; j++) {
$matches[j] = $matches[j].replace(/\]/g, '');
}
fields = [];
for (j = 0; j < len; j++) {
if ($matches[j] || j < len - 1) {
fields.push($matches[j].replace("'", ''));
}
}
if ($matches[len - 1] === '') {
offset = assign_object(result, fields, [], true, false, false);
if (value.constructor === Array) {
offset[0][offset[1]].concat(value);
} else {
offset[0][offset[1]].push(value);
}
} else {
assign_object(result, fields, value);
}
}
}
return result;
}
它是我的库phery的一部分,但可以移植到您自己的项目中。它在应该有数组的地方创建数组,从select、normalize复选框等选项中获取正确的选择选项。如果要将其转换为JSON(真正的JSON字符串),只需执行JSON.stringify($('form').serializeForm());
其他回答
我发现所选解决方案有问题。
当使用具有基于数组的名称的表单时,jQueryserializeArray()函数实际上会失效。
我有一个PHP框架,它使用基于数组的字段名,允许在多个视图中将同一表单多次放在同一页面上。这可以方便地将添加、编辑和删除都放在同一页上,而不会出现表单模型冲突。
由于我想在不使用这种绝对基本功能的情况下对表单进行序列化,我决定编写自己的seralizeArray():
var $vals = {};
$("#video_edit_form input").each(function(i){
var name = $(this).attr("name").replace(/editSingleForm\[/i, '');
name = name.replace(/\]/i, '');
switch($(this).attr("type")){
case "text":
$vals[name] = $(this).val();
break;
case "checkbox":
if($(this).attr("checked")){
$vals[name] = $(this).val();
}
break;
case "radio":
if($(this).attr("checked")){
$vals[name] = $(this).val();
}
break;
default:
break;
}
});
请注意:这也适用于表单submit()之外,因此如果在代码的其余部分发生错误,如果您单击“保存更改”的链接按钮,表单将不会提交。
还请注意,此函数不应仅用于验证表单以收集要发送到服务器端进行验证的数据。使用这种弱的和大量分配的代码将导致XSS等。
对于语义ui/formantic ui,有一个内置的行为get值:
const fields = $("#myForm.ui.form").form('get values');
const jsonStr = JSON.stringify(fields);
看见https://fomantic-ui.com/behaviors/form.html#/settings
get-values(标识符)返回与标识符数组匹配的元素值的对象。如果未通过IDS,将返回所有字段
创建地图并循环所有字段,保存其值。
var params = {};
$("#form").find("*[name]").each(function(){
params[this.getAttribute("name")] = this.value;
});
这和你想要的完全一样
仅执行以下代码一次
$.fn.serializeObject = function(){
let d={};
$(this).serializeArray().forEach(r=>d[r.name]=r.value);
return d;
}
现在您可以多次执行以下行
let formObj = $('#myForm').serializeObject();
// will return like {id:"1", username:"abc"}
我喜欢塞缪尔的版本,但我相信它有一个小错误。通常JSON发送为
{“coreSKU”:“PCGUYJS”,“name_de”:“whatever”,。。。
不作为
〔{“coreSKU”:“PCGUYJS”},{“name_de”:“whatever”},。。。
因此,功能IMO应为:
App.toJson = function( selector ) {
var o = {};
$.map( $( selector ), function( n,i )
{
o[n.name] = $(n).val();
});
return o;
}
并将其包装在数据数组中(正如通常预期的那样),最后将其作为跨页发送App.stringify({data:App.toJson(“#cropform:input”)})
对于精简版本,请参见问题3593046,对于所有可能的版本,请参阅json2.js。这应该涵盖了所有内容:)