0

I need to generate html table dynamically and list driver_id underneath. It is something similar to pivot but the problem is zone_name can change every day. I'm using jquery and linq.js.

so far what I have tried:

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);
});

It is giving me output in this way:

<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>

enter image description here

but I need output in this format: It should display zone_name as column name and underneath driver_id and first id should be zone_rank 1 and 2 and so on.. enter image description here

3
  • Mapping the pivot not very difficult but not clear what issue is with zone name changes every day? Is that just a sorting issue? So long as property name is always the same shouldn't be an issue Commented May 27, 2018 at 18:32
  • they delete couple of zones and create single zone when it is not peak or create new zone when they start receiving calls from the far distance (out of all zones) Commented May 27, 2018 at 18:42
  • OK...so only issue is number of zones may change Commented May 27, 2018 at 19:02

2 Answers 2

1

So from what I could gather from your question, you're trying to group data items by zone, then outputting them in a table where the columns are the zones. Linq.js can handle this well, it'll just have some problems with transposing the data rows to columns.

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);
}
Sign up to request clarification or add additional context in comments.

Comments

0

Am not familiar with linq.js so I used native array method Array#reduce() and Map object to create unique zones

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>

1 Comment

Great! Thank you, it works as expected, one more thing, how can we bind an event to each driver ID <td>?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.