//original JSON
const srcJSON = {"alertItems":[{"id":"PROD-115388","errors":["Original Estimate is null","id is null"],"warnings":["Original Estimate is above threshold","Story points are above threshold","These sub tasks are not defined"]},{"id":"PROD-112479","errors":[],"warnings":["OriginalEstimateisabovethreshold","Storypointsareabovethreshold","Estimateismissingforthesesubtasks: PROD-112329"]},{"id":"PROD-108461","errors":[],"warnings":["OriginalEstimateisabovethreshold","Storypointsareabovethreshold","Thesesubtasksarenotdefined: TestCase, BADocumentationTask, QADesignandExecuteTask, BA/QA/Dev, BATestingTask, QADocumentationTask, Elaboration"]}],"numberOfErrors":0,"numberOfWarnings":10};
//proper JSON
const transform = data => data.alertItems.map(({id, errors, warnings}) => [...errors.map(error => ({id, type: 'error', reason: error})),...warnings.map(warning => ({id, type: 'warning', reason:warning}))]).flat();
//datatables init
$('table').DataTable({
/*
ajax: {
url: //url to API endpoint returning original JSON
method: //http method (GET, POST, etc)
dataSrc: transform(data)
}
*/
data: transform(srcJSON), //this one should be dropped once ajax section uncommented
paging: false,
orderFixed: [0,'asc'],
columns: [
{data: 'id', title: 'Story Id'},
{data: 'type', title: 'Type'},
{data: 'reason', title: 'Warning Reason'}
],
//group by first col, using rowspan attribute
drawCallback: function(){
//clean up the view
$('tbody td').attr('rowspan',1).show();
//grab datatable into variable
const table = this.api();
//grab visible, sorted table rows
const rows = table.rows({search:'applied',order:'current'}).nodes();
var groupIdTd = null;
//run through the table rows and set 'rowspan' attribute for matching id's
$.each(rows, function(idx){
const rowspan = Number($(groupIdTd).attr('rowspan') || 1);
idx > 0 && table.cell(groupIdTd).data() == table.cell(this,0).data() ?
($(groupIdTd).attr('rowspan', rowspan+1), $(table.cell(this,0).node()).hide()) :
(groupIdTd = table.cell(this,0).node(), $(groupIdTd).attr('rowspan',1));
});
}
})
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/jq-3.3.1/dt-1.10.18/rg-1.1.0/datatables.min.css" />
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/rowgroup/1.1.0/css/rowGroup.dataTables.min.css" />
<script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/v/dt/jq-3.3.1/dt-1.10.18/rg-1.1.0/datatables.min.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/rowgroup/1.1.0/js/dataTables.rowGroup.min.js"></script>
<script src="test.js"></script>
</head>
<body>
<table></table>
</body>
</html>