序列化表单数据时保留分组

Preserve grouping when serializing form data

我有一个 HTML 表单,其中包含相似的输入元素组。

如何在不迭代输入元素的情况下在保留分组的同时序列化表单数据?

如果需要实现目标,我愿意更改表单结构。

示例输入:

<form id="form">
  <div>
    <input name="id" value="1" type="hidden">
    <input name="quantity" value="10">
  </div>
  <div>
    <input name="id" value="2" type="hidden">
    <input name="quantity" value="20">
  </div>
  <div>
    <input name="id" value="3" type="hidden">
    <input name="quantity" value="30">
  </div>
</form>

预期输出:

{
  "1": { "id": "1","quantity": "10" },
  "2": { "id": "2","quantity": "20" },
  "3": { "id": "3","quantity": "30" }
}

我试过了:

console.log($('#form').serializeArray());

但是表单数据没有分组:

[
  {"name":"id","value":"1"},{"name":"quantity","value":"10"},
  {"name":"id","value":"2"},{"name":"quantity","value":"20"},
  {"name":"id","value":"3"},{"name":"quantity","value":"30"}
]
var arr = []

$($('form').prop('elements')).each(function(e){
 arr.push({
  "id": e,
  "qty": this.value
 });
});
console.log(arr);

试试这个。

FormData 构造函数——当传递一个对表单节点的引用时——returns 一个包含所有表单控件及其各自值的迭代器。

const form = document.querySelector("#form");
const data = new FormData(form);

console.log(Array.from(data));
// [["id","1"],["quantity","10"],["id","2"],["quantity","20"],["id","3"],["quantity","30"]]

问题是 FormData 没有任何方法可以对表单控件进行分组。这将需要一种算法,而算法又需要某种方法来识别给定控件属于哪个组。

这里我在每个表单控件的名称属性前加上了组标识符和冒号。在算法中,我用冒号分割名称属性,使用第一个结果作为组,第二个结果作为键。

const form = document.querySelector("#form");
const data = new FormData(form);

const grouped = Array.from(data).reduce((m, e) => 
  ((([g, k, v] = [...e[0].split(':'), e[1]]) =>  
    (m[g] = Object.assign({}, m[g]))[k] = v)(), m), {});

console.log(grouped);
<form id="form">
  <input name="1:id" value="1" type="hidden"><input name="1:quantity" value="10">
  <input name="2:id" value="2" type="hidden"><input name="2:quantity" value="20">
  <input name="3:id" value="3" type="hidden"><input name="3:quantity" value="30">
</form>

你可以这样做:

(function($){
  $(function(){
    $("#RunCode").click(function(e){
      var FormData = [];
      $("#form input.serialize").each(function(){
        var name = $(this).attr("name");
        name = name.split("[")
        var id = name[1].replace("]", "");
        name = name[0];
        if(typeof FormData[id] == "undefined"){ FormData[id] = {}; }
        FormData[id][name] = $(this).val();
        console.log(name, id, $(this).val(), FormData);
      });
      var str = JSON.stringify(FormData);
      alert(str);
      
      e.preventDefault();
      return false;
    });
  });
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="form">
    <div>
    <input class="serialize" type="hidden" name="id[0]" value="1">
    <input class="serialize" name="quantity[0]" min="0" type="text" value="10" />
    </div>
    <div>
    <input class="serialize" type="hidden" name="id[1]" value="2">
    <input class="serialize" name="quantity[1]" min="0" type="text" value="20" />
    </div>
    <div>
    <input class="serialize" type="hidden" name="id[2]" value="3">
    <input class="serialize" name="quantity[2]" min="0" type="text" value="30" />
    </div>
    <input type="button" id="RunCode" value="Run Code" />
</form>