2017-02-09 68 views
0

我有以下陣列:動態追加多的TR

arr = [{ 
    "ID": 1, 
    "animals": { 
    "dog": { 
     "color": "brown", 
     "age": 5 
    }, 
    "cat": { 
     "color": "white", 
     "age": 3 
    } 
    } 
}, { 
    "ID": 2, 
    "animals": { 
    "cat": { 
     "color": "black", 
     "age": 7 
    } 
    } 
}, { 
    "ID": 3, 
    "animals": { 
    "mouse": { 
     "color": "white", 
     "age": 1 
    }, 
    "dog": { 
     "color": "black", 
     "age": 9 
    }, 
    "cat": { 
     "color": "grey", 
     "age": 4 
    } 
    } 
}] 

我需要這個表出來的是:

desired table

或者爲代碼:

<table border="1" id="myTab"> 
    <tr> 
    <td>ID</td> 
    <td>Animal</td> 
    <td>Color</td> 
    <td>Age</td> 
    </tr> 
    <tr> 
    <td rowspan="2">1</td> 
    <td>cat</td> 
    <td>3</td> 
    <td>white</td> 
    </tr> 
    <tr> 
    <td>dog</td> 
    <td>5</td> 
    <td>brown</td> 
    </tr> 
    <tr> 
    <td rowspan="1">2</td> 
    <td>cat</td> 
    <td>7</td> 
    <td>black</td> 
    </tr> 
    <tr> 
    <td rowspan="3">3</td> 
    <td>mouse</td> 
    <td>1</td> 
    <td>white</td> 
    </tr> 
    <tr> 
    <td>dog</td> 
    <td>9</td> 
    <td>black</td> 
    </tr> 
    <tr> 
    <td>cat</td> 
    <td>4</td> 
    <td>grey</td> 
    </tr> 
</table> 

Here我學會了如何合併多個tr的正確方法。

但儘管如此,它不會在我的工作,例如:

$.each(arr, function(key, value) { 
    var rowspan = Object.keys(arr[key].animals).length; 

    var tr = ""; 
    c = 0; 
    $.each(value, function(key2, value2) { 
    if (key2 != "animals") { 
     if (rowspan < 1) { 
     rowspan = 1; 
     } 
     tr += '<td rowspan=' + rowspan + '>' + value2 + '</td>'; 
    } else { 
     $.each(value2, function(key3, value3) { 
     var tr2_temp = ""; 

     tr2_temp += "<td>" + key3 + "</td>"; 
     $.each(value3, function(key4, value4) { 
      tr2_temp += "<td>" + value4 + "</td>"; 
     }); 

     if (c == 0) { 
      $('#myTab tr:eq(' + parseInt(key + 1) + ')').append(tr2_temp) 
      c++; 
     } else { 
      $('#myTab tr:eq(' + parseInt(key + 1) + ')').after(tr2_temp) 
      c = 0; 
     } 
     }); 
    } 
    }); 
    $('#myTab > tbody:last-child').append('<tr>' + tr + '</tr>'); 
}); 

Here is a fiddle

+0

如果你硬編碼你的表標記,基於陣列上,什麼是你想看到作爲輸出的表結構?基於代碼,看起來有一些合理的選擇,所以看到實際的輸出是什麼,你期望有很大的幫助。 – Nope

+0

@Fran:我添加了所需表格的代碼。 – user1170330

回答

0
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> 
<script> 
arr = [{ 
    "ID": 1, 
    "animals": { 
    "dog": { 
     "color": "brown", 
     "age": 5 
    }, 
    "cat": { 
     "color": "white", 
     "age": 3 
    } 
    } 
}, { 
    "ID": 2, 
    "animals": { 
    "cat": { 
     "color": "black", 
     "age": 7 
    } 
    } 
}, { 
    "ID": 3, 
    "animals": { 
    "mouse": { 
     "color": "white", 
     "age": 1 
    }, 
    "dog": { 
     "color": "black", 
     "age": 9 
    }, 
    "cat": { 
     "color": "grey", 
     "age": 4 
    } 
    } 
}] 

function getAttr(obj) { 
var props; 
for (var prop in obj) { 
    props += '<td>'+obj[prop]+'</td>'; 
    } 
    return props; 
} 

function extractChildren(animal,obj) { 
    return '<td>'+animal+'</td>' + getAttr(obj) + ''; 
} 
function addRows() { 
    for(var i=0; i<arr.length; i++) { 
    var children = []; 
    var rows = 0; 

    for (var prop in arr[i].animals) { 
     rows++; 
     children.push(extractChildren(prop,arr[i].animals[prop])); 
    } 
    $('#tbl tbody').append(
    `<tr> 
     <td rowspan="`+rows+`">`+ arr[i].ID+ `</td>`+children[0]+` 
    </tr>` 
    ); 
    children.shift(); 
    for(var j=0; j<children.length; j++) { 
     $('#tbl tbody').append(`<tr>`+children[j]+`</tr>`); 
    } 
    } 
} 
$(document).ready(function() { 
    addRows(); 
}); 
</script> 
<table id="tbl" border="1"> 
    <thead> 
    <th>ID</th> 
    <th>Animal</th> 
    <th>Colour</th> 
    <th>Age</th> 
    </thead> 
    <tbody> 
    </tbody> 
+0

'thead','tfoot'和'tbody'是可選的,將元素附加到DOM內部的循環以及執行'.find'是實現它的最低效的方式,並且可能會減慢頁面的渲染速度少於100行處理。 – Nope

+0

它們是可選的,但是完全有效,關於動態添加TR的問題,我們如何避免將元素附加到DOM?你的答案也使用一個循環與追加。但正確的發現並不需要我已經調整了答案 –

+0

我沒有附加到循環內的DOM,因爲這將是非常糟糕的。我將其附加到內存中,並且只在完成後才附加到DOM 1次。關於表格標記,我們通常嘗試使用給定的標記給出答案(除非開始時無效),以防OP不能改變它,然後在可能的情況下留下改進建議。想象一下基於修正標記的解決方案,用戶不能更改:(但是,在這種情況下,它並不重要。 – Nope

1

儘管我會建議您不要將動物類型用作屬性名稱,因爲如果您有多個相同類型的動物,而是使用屬性(可能命名爲type,值爲dog, cat, etc.. ,使用你現有的條件你可以像下面這樣做。

此外,我建議您先寫入內存中的變量,然後對DOM執行一個附加操作。

arr = [{ 
 
    "ID": 1, 
 
    "animals": { 
 
     "dog": { 
 
      "color": "brown", 
 
      "age": 5 
 
     }, 
 
     "cat": { 
 
      "color": "white", 
 
      "age": 3 
 
     } 
 
    } 
 
}, { 
 
    "ID": 2, 
 
    "animals": { 
 
     "cat": { 
 
      "color": "black", 
 
      "age": 7 
 
     } 
 
    } 
 
}, { 
 
    "ID": 3, 
 
    "animals": { 
 
     "mouse": { 
 
      "color": "white", 
 
      "age": 1 
 
     }, 
 
     "dog": { 
 
      "color": "black", 
 
      "age": 9 
 
     }, 
 
     "cat": { 
 
      "color": "grey", 
 
      "age": 4 
 
     } 
 
    } 
 
}] 
 

 
var rowspanTemplate = '<tr><td rowspan="{0}">{1}</td><td>{2}</td><td>{3}</td><td>{4}</td></tr>' 
 
var simpleTemplate = '<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>' 
 
var $newRows = $('<div></div>'); 
 

 
$.each(arr, function(key, value) { 
 
    var newRow; 
 
    var animalTypes = Object.keys(value.animals); 
 
    var i; 
 
    var animalType; 
 

 
    for (i = 0; i < animalTypes.length; i++) { 
 
     animalType = animalTypes[i]; 
 

 
     if (i === 0) { 
 
      newRow = rowspanTemplate 
 
       .replace('{0}', animalTypes.length) 
 
       .replace('{1}', value.ID) 
 
       .replace('{2}', animalType) 
 
       .replace('{3}', value.animals[animalType].color) 
 
       .replace('{4}', value.animals[animalType].age) 
 
     } else { 
 
      newRow = simpleTemplate 
 
       .replace('{0}', animalTypes[i]) 
 
       .replace('{1}', value.animals[animalType].color) 
 
       .replace('{2}', value.animals[animalType].age) 
 
     } 
 

 
     $newRows.append($(newRow)); 
 
    } 
 
}) 
 

 
$('#myTab').append($newRows.html());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<table border="1" id="myTab"> 
 
    <tr> 
 
    <td>ID</td> 
 
    <td>Animal</td> 
 
    <td>Color</td> 
 
    <td>Age</td> 
 
    </tr> 
 
</table>

+0

在我的真實情況下,有> 20個不同的列。有什麼辦法可以使它更加動態,而不是取代它們中的每一個? – user1170330

+0

@ user1170330你可以使用angular,knockout或者類似的方法爲你做這件事,但是對於這樣一個簡單的映射,除非你已經在使用它們,否則我不會引入這種重度依賴關係:)即使有100列,必須寫映射器,就是這樣。把它作爲一個函數,傳入數組的一部分,並返回帶有映射值的'tr'。這樣你也可以獨立地寫映射器的單元測試。你也可以編寫一個'string.format'擴展,傳遞參數數組來動態地將'{x}'替換爲相同位置的值。 – Nope