根据选定的嵌套复选框生成JSON

时间:2018-07-02 09:06:21

标签: javascript jquery arrays json object

我已经基于JSON以嵌套方式动态创建了一组复选框输入。现在,我想以父子形式将所有选中的复选框作为数组,如下所示:

MASTERDATA
+------------+----------+-------------+------------------------------+------+-------+------------+---------+-----------------+----------------+
| partnumber | partname | description | imageurl                     | qty  | oemid | seriesid   | modelid | functiongroupid | assemblynameid |
+------------+----------+-------------+------------------------------+------+-------+------------+---------+-----------------+----------------+
| A32        | Lens     | RED         | AP3415_________UN01JAN94.gif | 2    |     8 |        256 |    6694 |           12318 |         449980 |
| 14274      | Nut      | M10         | TX1061736______UN20JUL09.gif | 1    |     8 |        257 |    8264 |           13996 |         884056 |
| C1115      | HC       | NLA ORDER   | 0000897883____________A2.gif | 1    |     8 |        258 |    8263 |           13962 |         880092 |
| 03H1626    | BOLT     | 1/4 X 1/2   | M5004__________UN02JAN94.gif | 1    |     8 |        259 |    6693 |           17549 |          89782 |
| 1854       | Screw    | M10 X 80    | TX1030795______UN25OCT07.gif | 4    |     8 |        260 |    8262 |           14029 |         891643 |
+------------+----------+-------------+------------------------------+------+-------+------------+---------+-----------------+----------------+
let data = {
  "personal-information": {
    "label": "personal-information",
    "children": {
      "first_name": {
        "type": "string",
        "label": "First Name",
        "optional": false
      },
      "last_name": {
        "type": "string",
        "label": "Last Name",
        "optional": false
      },
      "dob": {
        "type": "date",
        "label": "Date Of Birth",
        "optional": false
      },
      "gender": {
        "type": "string",
        "label": "Gender",
        "optional": false
      },
      "height": {
        "type": "string",
        "label": "Height",
        "optional": false
      },
      "weight": {
        "type": "string",
        "label": "Weight",
        "optional": false
      },
      "blood-group": {
        "type": "string",
        "label": "Blood-Group",
        "optional": false
      },
      "addresses": {
        "label": "addresses",
        "children": {
          "address-line-1": {
            "type": "string",
            "label": "Address",
            "optional": false
          },
          "address-line-2": {
            "type": "string",
            "label": "Address",
            "optional": false
          },
          "city": {
            "type": "string",
            "label": "City",
            "optional": false
          },
          "state": {
            "type": "string",
            "label": "State",
            "optional": false
          },
          "country": {
            "type": "string",
            "label": "Country",
            "optional": false
          },
          "zipcode": {
            "type": "string",
            "label": "Zip Code",
            "optional": false
          }
        }
      },
      "emergency-contact": {
        "label": "emergency-contact",
        "children": {
          "name": {
            "type": "string",
            "label": "Zip Code",
            "optional": false
          },
          "phone": {
            "type": "string",
            "label": "Phone",
            "optional": false
          },
          "email": {
            "type": "string",
            "label": "Email",
            "optional": false
          }
        }
      }
    }
  },
  "general-information": {
    "label": "general-information",
    "children": {
      "allergies": {
        "type": "String",
        "label": "Allergies",
        "optional": true
      },
      "habits": {
        "type": "String",
        "label": "Habits",
        "optional": true
      }
    }
  },
  "history": {
    "label": "history",
    "children": {
      "status": {
        "type": "Boolean",
        "label": "Status",
        "optional": false
      },
      "createdAt": {
        "type": "date",
        "label": "createdAt",
        "optional": false
      },
      "problem": {
        "type": "Text",
        "label": "Chief Complaint",
        "optional": true
      },
      "diagnosis": {
        "type": "Text",
        "label": "Diagnosis",
        "optional": true
      },
      "prescription": {
        "type": "Text",
        "label": "Prescription",
        "optional": true
      },
      "lab-result": {
        "label": "lab-result",
        "children": {
          "test-name": {
            "type": "string",
            "label": "Test Name",
            "optional": false
          },
          "loinc": {
            "type": "string",
            "label": "Loinc",
            "optional": false
          },
          "normal-range": {
            "type": "string",
            "label": "Normal Range",
            "optional": false
          },
          "unit": {
            "type": "string",
            "label": "Unit",
            "optional": false
          },
          "value": {
            "type": "string",
            "label": "Value",
            "optional": false
          },
          "test-result": {
            "type": "string",
            "label": "Test Name",
            "optional": false
          },
          "createdAt": {
            "type": "date-time",
            "label": "Time",
            "optional": false
          },
          "status": {
            "type": "Boolean",
            "label": "Status",
            "optional": false
          }
        }
      },
      "medication-history": {
        "label": "medication-history",
        "children": {
          "medication-name": {
            "type": "string",
            "label": "Medication Name",
            "optional": false
          },
          "notes": {
            "type": "string",
            "label": "Notes",
            "optional": false
          },
          "status": {
            "type": "Boolean",
            "label": "Status",
            "optional": false
          },
          "qty": {
            "type": "string",
            "label": "Quantity",
            "optional": false
          },
          "time-to-take": {
            "type": "string",
            "label": "No. of time to take",
            "optional": false
          },
          "createdAt": {
            "type": "date",
            "label": "Date",
            "optional": false
          }
        }
      }
    }
  }
};
let nodeLevel = 1;

function addItem(parentUL, branch, parentName) {
  for (var key in branch) {
    // console.log('Branch', branch[key]);
    // console.log('Key: ', key);
    var item = branch[key].children;
    // console.log('Item: ', item)

    let name = '';

    if (parentName) {
      name = parentName;
    }

    $item = $('<li>', {
      id: key
    });
    $item.append($('<input>', {
      type: "checkbox",
      id: key,
      name: key,
      value: key,
      "data-parent": name
    }));
    // $item.attr('data-parent', name);
    $item.append($('<label>', {
      for: key,
      text: key
    }));
    parentUL.append($item);
    nodeLevel++;
    if (branch[key].children) {
      var $ul = $('<ul>', {
        style: 'display: none'
      }).appendTo($item);

      addItem($ul, item, branch[key].label);
    } else {
      nodeLevel = 1;
    }
  }
}

$(function() {
  addItem($('#root'), data);
  $(':checkbox').change(function() {
    $(this).closest('li').children('ul').slideToggle();
  });

  // $('label').click(function() {
  //   $(this).closest('li').find(':checkbox').trigger('click');
  // });
});



$(".save").click(function() {

  var selected = new Array();

  var checkboxes = document.querySelectorAll('input[type=checkbox]:checked')

  let arrAll = {};
  for (var i = 0; i < checkboxes.length; i++) {
    let parent = checkboxes[i].getAttribute('data-parent');

    console.log('Checkbox: ', checkboxes[i]);
    console.log('Parent: ', parent);

    // let inputName = checkboxes[i].getAttribute('name');



    // console.log(inputName);

    // if(parent) {
    // 	arrAll[parent][inputName] = {};
    // } else {

    // 	arrAll[inputName] = {};	
    // }

    /*
    if(parent){
    	selected[parent] = [];
    	selected[parent].push(checkboxes[i].value);
    } else {
    	selected.push(checkboxes[i].value);
    } */
    // selected.push(checkboxes[i].value)
  }

  // console.log('Selected checkbox:', arrAll);

});

所以,如果我选择 1.个人信息->名和姓 2.个人信息->地址->地址行1 3.一般信息->过敏 4.历史记录->状态

我的预期输出是:

ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

ul ul {
  margin: 0 0 0 30px;
}

我该如何使用jQuery或Javascript?

1 个答案:

答案 0 :(得分:2)

您可以像在创建元素时一样,以递归方式再次遍历data对象以读取状态。我们从所需的结构开始,而不是从复选框的数组开始。

在此示例中,我使用name属性将UI元素与原始数据源进行匹配。最好在创建它的某个时候存储对它的引用。这样可以更轻松地找到合适的元素,而不必依赖DOM查询。

还要注意,您当前的HTML在<li><checkbox>元素上包含重复的ID ...

简而言之:

  • 遍历data的条目
  • 对于每个键,找到一个[name=${key}]元素
  • 如果元素为checked,则将其key添加到对象
  • 如果值包含children对象,请递归。
  • 如果该值不包含children,请添加其值
const walkCheckedTree = (opts) => Object
    .entries(opts)
    .reduce((t, [k, v]) => {
      const cb = root.querySelector(`[name=${k}]`);

      if (cb.checked) {
        if (v.children) {
          t[k] = { child: walkCheckedTree(v.children) };
        } else {
          t[k] = k;
        }
      }

      return t;
    }, {});

const tree = walkCheckedTree(data);

运行示例:(按保存以记录日志)

let data = {
  "personal-information": {
    "label": "personal-information",
    "children": {
      "first_name": {
        "type": "string",
        "label": "First Name",
        "optional": false
      },
      "last_name": {
        "type": "string",
        "label": "Last Name",
        "optional": false
      },
      "dob": {
        "type": "date",
        "label": "Date Of Birth",
        "optional": false
      },
      "gender": {
        "type": "string",
        "label": "Gender",
        "optional": false
      },
      "height": {
        "type": "string",
        "label": "Height",
        "optional": false
      },
      "weight": {
        "type": "string",
        "label": "Weight",
        "optional": false
      },
      "blood-group": {
        "type": "string",
        "label": "Blood-Group",
        "optional": false
      },
      "addresses": {
        "label": "addresses",
        "children": {
          "address-line-1": {
            "type": "string",
            "label": "Address",
            "optional": false
          },
          "address-line-2": {
            "type": "string",
            "label": "Address",
            "optional": false
          },
          "city": {
            "type": "string",
            "label": "City",
            "optional": false
          },
          "state": {
            "type": "string",
            "label": "State",
            "optional": false
          },
          "country": {
            "type": "string",
            "label": "Country",
            "optional": false
          },
          "zipcode": {
            "type": "string",
            "label": "Zip Code",
            "optional": false
          }
        }
      },
      "emergency-contact": {
        "label": "emergency-contact",
        "children": {
          "name": {
            "type": "string",
            "label": "Zip Code",
            "optional": false
          },
          "phone": {
            "type": "string",
            "label": "Phone",
            "optional": false
          },
          "email": {
            "type": "string",
            "label": "Email",
            "optional": false
          }
        }
      }
    }
  },
  "general-information": {
    "label": "general-information",
    "children": {
      "allergies": {
        "type": "String",
        "label": "Allergies",
        "optional": true
      },
      "habits": {
        "type": "String",
        "label": "Habits",
        "optional": true
      }
    }
  },
  "history": {
    "label": "history",
    "children": {
      "status": {
        "type": "Boolean",
        "label": "Status",
        "optional": false
      },
      "createdAt": {
        "type": "date",
        "label": "createdAt",
        "optional": false
      },
      "problem": {
        "type": "Text",
        "label": "Chief Complaint",
        "optional": true
      },
      "diagnosis": {
        "type": "Text",
        "label": "Diagnosis",
        "optional": true
      },
      "prescription": {
        "type": "Text",
        "label": "Prescription",
        "optional": true
      },
      "lab-result": {
        "label": "lab-result",
        "children": {
          "test-name": {
            "type": "string",
            "label": "Test Name",
            "optional": false
          },
          "loinc": {
            "type": "string",
            "label": "Loinc",
            "optional": false
          },
          "normal-range": {
            "type": "string",
            "label": "Normal Range",
            "optional": false
          },
          "unit": {
            "type": "string",
            "label": "Unit",
            "optional": false
          },
          "value": {
            "type": "string",
            "label": "Value",
            "optional": false
          },
          "test-result": {
            "type": "string",
            "label": "Test Name",
            "optional": false
          },
          "createdAt": {
            "type": "date-time",
            "label": "Time",
            "optional": false
          },
          "status": {
            "type": "Boolean",
            "label": "Status",
            "optional": false
          }
        }
      },
      "medication-history": {
        "label": "medication-history",
        "children": {
          "medication-name": {
            "type": "string",
            "label": "Medication Name",
            "optional": false
          },
          "notes": {
            "type": "string",
            "label": "Notes",
            "optional": false
          },
          "status": {
            "type": "Boolean",
            "label": "Status",
            "optional": false
          },
          "qty": {
            "type": "string",
            "label": "Quantity",
            "optional": false
          },
          "time-to-take": {
            "type": "string",
            "label": "No. of time to take",
            "optional": false
          },
          "createdAt": {
            "type": "date",
            "label": "Date",
            "optional": false
          }
        }
      }
    }
  }
};
let nodeLevel = 1;

function addItem(parentUL, branch, parentName) {
  for (var key in branch) {
    // console.log('Branch', branch[key]);
    // console.log('Key: ', key);
    var item = branch[key].children;
    // console.log('Item: ', item)

    let name = '';

    if (parentName) {
      name = parentName;
    }

    $item = $('<li>', {
      id: key
    });
    $item.append($('<input>', {
      type: "checkbox",
      id: key,
      name: key,
      value: key,
      "data-parent": name
    }));
    // $item.attr('data-parent', name);
    $item.append($('<label>', {
      for: key,
      text: key
    }));
    parentUL.append($item);
    nodeLevel++;
    if (branch[key].children) {
      var $ul = $('<ul>', {
        style: 'display: none'
      }).appendTo($item);

      addItem($ul, item, branch[key].label);
    } else {
      nodeLevel = 1;
    }
  }
}

$(function() {
  addItem($('#root'), data);
  $(':checkbox').change(function() {
    $(this).closest('li').children('ul').slideToggle();
  });

  // $('label').click(function() {
  //   $(this).closest('li').find(':checkbox').trigger('click');
  // });
});



$(".save").click(function() {
  const root = document.getElementById("root");
  
  const walkCheckedTree = (opts) => Object
    .entries(opts)
    .reduce((t, [k, v]) => {
      const cb = root.querySelector(`[name=${k}]`);

      if (cb.checked) {
        if (v.children) {
          t[k] = { child: walkCheckedTree(v.children) };
        } else {
          t[k] = k;
        }
      }
      
      return t;
    }, {});
  
  const tree = walkCheckedTree(data);
  
  console.log(tree);
});
ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

ul ul {
  margin: 0 0 0 30px;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

<ul id="root"></ul>

<button class="save">Save</button>