Динамически генерировать HTML-таблицу из данных JSON

Мне нужно динамически генерировать HTML-таблицу и список driver_id внизу. Это что-то похожее на pivot, но проблема в том, что zone_name может меняться каждый день. Я использую jquery и linq.js.

пока что попробовал

var data =
            [
                {
                    "ColorCode": "green",
                    "StatusName": "ACTIVE",
                    "rankId": 0,
                    "zone_name": "Zone A",
                    "driver_id": 100,
                    "zone_rank": 1,
                    "status_id": null,
                    "company_id": null,
                    "updated_on": null,
                    "Driver": null,
                    "login_status": null
                },
                {
                    "ColorCode": "yellow",
                    "StatusName": "BREAK",
                    "rankId": 0,
                    "zone_name": "Zone B",
                    "driver_id": 101,
                    "zone_rank": 1,
                    "status_id": null,
                    "company_id": null,
                    "updated_on": null,
                    "Driver": null,
                    "login_status": null
                },
                {
                    "ColorCode": "green",
                    "StatusName": "ACTIVE",
                    "rankId": 0,
                    "zone_name": "Zone A",
                    "driver_id": 102,
                    "zone_rank": 4,
                    "status_id": null,
                    "company_id": null,
                    "updated_on": null,
                    "Driver": null,
                    "login_status": null
                }
            ]

    var zTable = document.getElementById('tblZoneRank');
    var allzones = Enumerable.From(data)
                             .Distinct(p => p.zone_name)
                             .Select(p => p.zone_name).ToArray();

    $.each(allzones, function (i, item) {
    var tr = document.createElement('tr');
    var td = document.createElement("td");
    var txt = document.createTextNode(item);

    td.appendChild(txt);
    tr.appendChild(td);
    var childItem = Enumerable.From(data)
                              .Where(p => p.zone_name == item)
                              .ToArray();
    $.each(childItem, function (j, citem) {
        var ctd = document.createElement("td");
        var ctxt = document.createTextNode(citem.driver_id);

        ctd.appendChild(ctxt);
        $(ctd).css('background-color', citem.ColorCode);
        tr.appendChild(ctd);
    });
    zTable.appendChild(tr);
});

Это дает мне вывод таким образом:

<table id="tblZoneRank">
  <tr>
    <td>Zone A</td>
    <td style="background-color: rgb(0, 128, 0);">100</td>
    <td style="background-color: rgb(0, 128, 0);">102</td>
 </tr>
 <tr>
    <td>Zone B</td>
    <td style="background-color: rgb(255, 255, 0);">101</td>
 </tr>
</table>

но мне нужен вывод в этом формате: он должен отображать имя_зоны в качестве имени столбца и под драйвером_ид, а первым идентификатором должны быть Зоны_ранков 1 и 2 и т. д.

1 ответ

Решение

Я не знаком с linq.js, поэтому я использовал собственный метод массива Array#reduce() а также Map объект для создания уникальных зон

const $table = $('#zoneTable');

// creates Map object with zone names as keys and arrays of jQuery objects(cells) as values
const zoneMap = data.reduce((map, item) => {
  const col = map.get(item.zone_name) || [createCell(item.zone_name)];
  col.push(createCell(item.driver_id, item.ColorCode));
  return map.set(item.zone_name, col);
}, new Map());

// convert Map values to array of arrays. Each sub array is a table column
const colCells = [...zoneMap.values()];

const totalRows = Math.max(...colCells.map(e => e.length));

for (let i = 0; i < totalRows; i++) {
  const rowCells = colCells.map(col => col[i] || createCell());// fill any missing with empty cell
  const $row = $('<tr>').append(rowCells);
  $table.append($row)
}

// helper function to create cells
function createCell(text = '', color = null) {
  const $td = $('<td>').text(text);
  return color ? $td.css('background-color', color) : $td;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="zoneTable"></table>


<script>
  var data = [{
      "ColorCode": "green",
      "StatusName": "ACTIVE",
      "rankId": 0,
      "zone_name": "Zone A",
      "driver_id": 100,
      "zone_rank": 1,
      "status_id": null,
      "company_id": null,
      "updated_on": null,
      "Driver": null,
      "login_status": null
    },
    {
      "ColorCode": "yellow",
      "StatusName": "BREAK",
      "rankId": 0,
      "zone_name": "Zone B",
      "driver_id": 101,
      "zone_rank": 1,
      "status_id": null,
      "company_id": null,
      "updated_on": null,
      "Driver": null,
      "login_status": null
    },
    {
      "ColorCode": "green",
      "StatusName": "ACTIVE",
      "rankId": 0,
      "zone_name": "Zone A",
      "driver_id": 102,
      "zone_rank": 4,
      "status_id": null,
      "company_id": null,
      "updated_on": null,
      "Driver": null,
      "login_status": null
    }
  ]
</script>

Итак, из того, что я мог бы извлечь из вашего вопроса, вы пытаетесь сгруппировать элементы данных по зонам, а затем выводить их в таблицу, где столбцы являются зонами. Linq.js справится с этим хорошо, у него просто будут некоторые проблемы с переносом строк данных в столбцы.

const zTable = $('#tblZoneRank');
const rows = Enumerable.From(data)
  .GroupBy(p => p.zone_name, p =>
    $('<td></td>')
      .css({'background-color': p.ColorCode})
      .text(p.driver_id)
  )
  .Let(buildRows)
  .Select(rs =>
    $('<tr></tr>').append(rs)
  );
rows.ForEach(r => r.appendTo(zTable));

function buildRows(gs) {
  const header = gs.Select(g =>
    $('<th></th>').text(g.Key())
  ).ToArray();
  const rows = Enumerable.RepeatWithFinalize(
      () => gs.Select(g => g.GetEnumerator()).ToArray(),
      es => es.forEach(e => e.Dispose())
    )
    .Select(es => es.map(e => [e.MoveNext(), e.Current()]))
    .TakeWhile(xs => xs.reduce((a, x) => a || x[0], false))
    .Select(xs => xs.map(x => x[0] ? x[1] : $('<td></td>')));
  return Enumerable.Return(header).Concat(rows);
}
Другие вопросы по тегам