代码之家  ›  专栏  ›  技术社区  ›  Rakesh Adhikesavan

如何从javascript对象填充HTML表?

  •  1
  • Rakesh Adhikesavan  · 技术社区  · 8 年前

    data = {
        "Q1": [1,2,3,2],
        "Q2": [5,6,7,6],
        "Q3": [9,10,11,10]
    };
    

    在此基础上,我尝试生成下表:

    +----------+---------+--------+
    | Question | Options | Answer |
    +----------+---------+--------+
    | Q1       |       1 |      2 |
    +          +---------+        +
    |          |       2 |        |
    +          +---------+        +
    |          |       3 |        |
    +----------+---------+--------+
    | Q2       |       5 |      6 |
    +          +---------+        +
    |          |       6 |        |
    +          +---------+        +
    |          |       7 |        |
    +----------+---------+--------+
    | Q3       |       9 |     10 |
    +          +---------+        +
    |          |      10 |        |
    +          +---------+        +
    |          |      11 |        |
    +----------+---------+--------+
    

    question options answer

    "Q1": [1,2,3,2]
    

    Q1 Question 以及数组中的最后一个值 [1,2,3,2] Answer ,数组中的其余三个值将成为列下的三个单独行。 Options

    +----------+---------+--------+
    | Question | Options | Answer |
    +----------+---------+--------+
    | Q1       |       1 |      2 |
    +          +---------+        +
    |          |       2 |        |
    +          +---------+        +
    |          |       3 |        |
    +----------+---------+--------+
    

    JSFiddle

    data = {
        "Q1": [1,2,3,2],
        "Q2": [5,6,7,6],
        "Q3": [9,10,11,10]
    };
    
    //console.log(data);
    var tbody = document.getElementById('tbody');
    
    tbody.innerHTML += "<tr>" + 
                       "<th id='q'>" + "Question" + "</th>" +
                       "<th id='o'>" + "Options" + "</th>" +
                       "<th id='ca'>" + "Correct Answer" + "</th>" +
                       "</tr>"
    for (var question in data) {
    var tr = "<tr>";
    options = data[question];
    answer = options.pop();
    
    tr += "<td rowspan=" + options.length +" headers='q'>" + question + "</td>";
    for(var index in options){
    tr += "<td headers='o'>" + options[index] + "</td>"
    }
    tr +=  "<td headers='ca' rowspan=" + options.length + ">" + answer + "</td>" +
           "</tr>"
    tbody.innerHTML += tr;
    }
    <table class="table">
        <tbody id="tbody"></tbody>
    </table>
    1 回复  |  直到 8 年前
        1
  •  2
  •   Sphinx    8 年前

    我的解决方案:

    1. 可能有人会觉得这个步骤不必要,但我认为把它当作一个适配器,对于其他不同格式的数据,我们可以创建另一个适配器来格式化数据,然后不需要修改其余的代码(生成HTML)。然后添加一些验证器将使代码更强大。

    2. 合并所有HTML

    data = {
        "Q1": [1,2,3,2],
        "Q2": [5,6,7,6],
        "Q3": [9,10,11,10],
        'Q4': [], // test case 1: no data
        'Q5': [1], // test case 2: only answer field
        'Q6': ['A', 'B', 'C'],// test case 3: for string
        'Q7': ['TEST'] // test case 4: for answer(string) only
    };
    // For Q4, Q5, you can added some extra codes to uses default values intead, or ignore this row.
    
    // formmat the data first, add some validators if neccessary
    function formatAdapter (data) {
      return Object.entries(data).map((item) => {
      let newItem = {}
      newItem[item[0]] = {'options': item[1].slice(0, item[1].length -1),
        'answer': item[-1]} // assuming the last element is the answer, [0:last] is the options
      return [item[0], item[1].slice(0, item[1].length -1), item[1].slice(-1)[0]]
    })
    }
    let formmatedData = formatAdapter(data)
    
    var tbody = document.getElementById('tbody');
    
    // generate the header
    tbody.innerHTML += "<tr>" + 
                       "<th id='q'>" + "Question" + "</th>" +
                       "<th id='o'>" + "Options" + "</th>" +
                       "<th id='ca'>" + "Correct Answer" + "</th>" +
                       "</tr>"
    // generate the rows(Html) for each questions
    
    let rowHtmls = formmatedData.map((item) => {
      let row = '<tr><td rowspan="'+(item[1].length || 1) +'">'+item[0]+'</td>'
                + '<td>'+item[1][0]+'</td>'
                + '<td rowspan="'+(item[1].length || 1)+'">'+item[2]+'</td></tr>'
      row += item[1].slice(1).reduce((pre, cur) => {
        return pre + '<tr><td>'+cur+'</td></tr>'
      }, '')
      return row
    })
    
    // combine header(html) and rows(html)
    tbody.innerHTML += rowHtmls.reduce((pre, cur) => {
      return pre+cur
    }, '')
    table tbody tr td {
      border: 1px solid black
    }
    <table class="table">
        <tbody id="tbody"></tbody>
    </table>