从JSON构建动态表

时间:2014-12-10 21:43:20

标签: javascript json parsing

过去几天我一直在努力构建这个动态表。我已经用几种不同的方式构建了它,并且最终得到了我有正确输出的点,但是我所做的工作是手动的。我希望有人能帮我把它变得更有活力。

这是我的JSON(超简化)

的一个例子
var obj1 = {
"Summary" : 
[
{
    "ID" : "1234", 
    "Name" : "John", 
    "Status" : "Green",
},
{
    "ID" : "5678", 
    "Name" : "Mike", 
    "Status" : "Green",
},
{
    "ID" : "9012", 
    "Name" : "Tom", 
    "Status" : "Red",
},
{
    "ID" : "3456", 
    "Name" : "Chris", 
    "Status" : "Red",
},
{
    "ID" : "2445", 
    "Name" : "Pat", 
    "Status" : "Green",
},
{
    "ID" : "6543", 
    "Name" : "James", 
    "Status" : "Red",
}

]
};

我需要输出看起来像这样(它是这样的),但是我的数组中可能有超过6个对象,所以我需要遍历它而不是手工构建它。

1234   5678    9012    3456    2445    6543
John   Mike     Tom    Chris   Pat     James
Green  Green   Red     Red     Green   Green

到目前为止,这是我的代码。任何帮助将不胜感激。

for (j in obj1.Summary[0]) {
document.write('<tr><td class="' + j +'">' + j + '</td><td class="' + j +'">' +     obj1.Summary[0][j] + '</td><td class="' + j +'">' + obj1.Summary[1][j] + '</td><td class="' + j +'">' + obj1.Summary[2][j] + '</td><td class="' + j +'">' + obj1.Summary[3][j] + '</td><td class="' + j +'">' + obj1.Summary[4][j] + '</td><td class="' + j +'">' + obj1.Summary[5][j] + '</td></tr>');
}

4 个答案:

答案 0 :(得分:2)

我最近提出了一个有趣的模式,用于动态地从数据库输出创建表,同时保持对相关创建元素的引用以及用于创建它们的值。

这个方法对我来说很方便,因为我为每个表格单元格创建了输入元素,然后利用创建的结构根据实际值检查原始值,并根据更改的字段生成sql更新查询。

我意识到这对于这种特定情况可能有点过头了,但它确实有助于提高可读性和可维护性,所以我将它发布在这里,以防将来可能帮助其他人。

&#13;
&#13;
var responseText = {"Summary":[{"ID":"1234","Name":"John","Status":"Green",}, {"ID":"5678","Name":"Mike","Status":"Green",}, {"ID":"9012","Name":"Tom","Status":"Red",}, {"ID":"3456","Name":"Chris","Status":"Red",}, {"ID":"2445","Name":"Pat","Status":"Green",}, {"ID":"6543","Name":"James","Status":"Red",}]};

var list = new List(responseText.Summary);
document.body.appendChild(list.node);

function List(data) {
    if(!(this instanceof List)) return false;
    var list = this.node = document.createElement('div');
    list.setAttribute('class','list');
    var items  = this.items = {};
    for(var i in data) {
        items[i] = new ListItem(data[i])
        list.appendChild(items[i].node);
    }
}
function ListItem(data) {
    if(!(this instanceof ListItem)) return false;
    var item  = this.node  = document.createElement('div');
    item.setAttribute('class','item');
    var lines = this.lines = {};
    for(var i in data) {
        lines[i] = new ListItemLine(i, data[i])
        item.appendChild(lines[i].node);
    }
}
function ListItemLine(name, value) {
    if(!(this instanceof ListItemLine)) return false;
    var line = this.node = document.createElement('div');
    this.name = name;
    this.value = value;
    line.setAttribute('class','line ' + name);
    if(name !== 'ID')
        line.setAttribute('contenteditable', true);
    line.appendChild(document.createTextNode(value));
}
&#13;
.item {
    display: inline-block;
    padding: 5px;
    text-align: center;
}
&#13;
&#13;
&#13;

然后我在List类中使用了与此类似的东西,

list.onkeydown = function(e) {
    if(e.which !== 13) return true;
    e.preventDefault();
    var changes = [];
    for(var i in items) (function(item, data){
        for(var i in data.lines) (function(line){
            var value = line.value, 
                actual = line.node.textContent;
            if(value !== actual) changes.push({
                id: data.lines['ID'].value,
                name: line.name,
                value: actual
            });
        })(data.lines[i]);
    })(i, items[i]);
    console.log(encodeURIComponent(JSON.stringify(changes)));
}

在不使用console.log的情况下,我通过ajax将数据发送到生成update sql的接收者页面并返回查询结果。当然,有很多方法可以做到最后一部分,这对我来说是最有用的。

答案 1 :(得分:1)

如果要重复逻辑,则应使用循环。https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for

for (var i=0; i < obj.Summary.length; i++) {
  var object = obj.Summary[i]
  // write to document
}

您应该转置数据,也可以更改界面。

1234  John  Green
5678  Mike  Green

您可能会发现渲染库也很有用,以避免弄乱字符串连接。

https://github.com/leonidas/transparency

修改

没问题,仍然使用循环。在循环中构建行并将它们连接在一起。请参阅mdn array docs,尤其是forEachjoin

// specify keys and init rows

var keys = [ "ID" ] 
var rows = {}

keys.forEach(function (key) {
  rows[key] = []
})

// ok now we have rows

console.log(rows)

// add table cells to rows

summaryObjects.forEach(function (object) {
  for (var key in object) {
    var cell = "<td>" + object[key] + "</td>"
    rows[key].push(cell)
  }
})

// now we have cells in the rows

console.log(rows)

// put together the table

keys.forEach(function (key) {
  document.write("<tr>" + rows[key].join('') + "</tr>")
})

我的意思是上面的转置,就像线性代数中的矩阵转置一样。您的数据如下所示:

[
  { key: value, key: value }
  { key: value, key: value }
]

你想要

{
  key: [ value, value ],
  key: [ value, value ]
}

答案 2 :(得分:1)

制作一个变量并将文本放在那里。这样,您可以使用嵌套循环构建它,然后将其插入文档中。我在PHP中做了类似的事情,它可以将db表作为嵌套数组并从中生成一个表。

var table = "<table>";

//we loop over the attributes since you want that format
for (userAttribute in obj1.Summary[0]) {
  //these are your headers/titles
  table += '<tr><th>' + userAttribute + '</th>';

  //and here we build a row getting the attribute from each user
  for (userIndex in obj1.Summary) {
    var user = obj1.Summary[userIndex];
    table += '<td>' + user[userAttribute] + '</td>';
  }  
  table += '</tr>'; //close that row and move on to the next attribute
}

//close out the table
table += '</table>';

document.write(table);

答案 3 :(得分:0)

我建议使用Handlebarsjs之类的模板来做到这一点。这样,你就可以将html与JavaScript分开,而且你不必添加这么多的&#39; +&#39;。

例如,您可以将其嵌入到您的html中。

<script id="template" type="text/x-handlebars-template">

    {{#each Summary}}

        <tr><td>{{this.ID}}</td>
            <td>{{this.Name}}</td>
            <td>{{this.Status}}</td>
        </tr>

    {{/each}}
</script>

我认为我弄乱了标签,但你明白了。

然后在脚本文件中,您可以编译模板并获取数据。有关http://handlebarsjs.com/

的更多信息
var PROJECT_METHOD ={

            handlerData:function(resJSON){

                var templateSource   = $("#template").html(),

                    template = Handlebars.compile(templateSource),

                    projectHTML = template(resJSON),

                    parser = new DOMParser(),

                    // the result
                    doc = parser.parseFromString(projectHTML, "text/html");
                    document.write(doc);

            },
            loadProjectData : function(){

                $.ajax({
                    url:"data.json",
                    method:'get',
                    success:this.handlerData
                });
            }
         };

         PROJECT_METHOD.loadProjectData();

希望它有所帮助。