Julian
Julian

Reputation: 393

DataTables How can I add row numbers on a table with ajax data source

I use Angular App and DataTables. In one of my components I have a DataTable which pulls data from an external API using the "ajax" property of the options object.

export class ChartsDetailsComponent implements OnInit {
  ngOnInit(): void {
   var opts: any = {
       ajax :{
          url: this.appConfigService.analyseConfig.chartsApiUrl + "/api/Charts/GetChartDetails?type=" + this.chartType,
          dataSrc: "ChartData." + this.chartType
       },
       columns:[
                  {title:"Name"},
                  {title:"Status"},
       ] 
   };
   var table = $('#details').DataTable(opts); 
  }
}

The returned data has the following structure:

{
"ChartData":{
            "FQCInLocalChart":[
                               ["EM/AC.08.2.01","Remote"],
                               ["EM/AC.08.2.03","Remote"]
                              ]
            }
 }

The FQCInLocalChart is dynamic. It is not static property. That's why in the dataSrc property I put "ChartData." + this.chartType, where this.chartType is a private property of the Angular component.

The data source contains only the columns that has to be displayed, but I would like to have a row number before the columns that are filled with the returned from the API data. Is there a way to achieve this behavior?

Thanks in advance Julian

Upvotes: 0

Views: 2572

Answers (2)

Julian
Julian

Reputation: 393

I managed to solve my problem. Here is how I've done it: First I've changed the dataSrc property to be function, not string:

export class ChartsDetailsComponent implements OnInit {
  chartType: string = "FQCInLocalChart";

  convertData(json: object){
     var ret = <Array<Array<string>>>json["ChartData"][this.chartType];
     ret.map((value)=>{
           value.unshift('');
         });
   return ret;
  }
  ngOnInit(): void {
    var opts: any = {
      ajax :{
      url: this.appConfigService.analyseConfig.chartsApiUrl + "/api/Charts/GetChartDetails?type=" + this.chartType,
      dataSrc: this.converData.bind(this)
      },
      columns:[
              {title:"Nr."},
              {title:"Name"},
              {title:"Status"},
      ] 
  };
  var table = $('#details').DataTable(opts); 
  table.on('order.dt search.dt', function () {
  table.column(0, { search: 'applied', order: 'applied' }).nodes().each(function (cell, i) {
    cell.innerHTML = i + 1;
    });
  });

 }
}

Basically I hook to the dataSrc function from the angular component and bind the context to be the class of the component, that is how I gained access to the this.chartType property, added another element in front of the element of the array (to hold the row number) and then at the end hook up the table.on() order and search events, to fill up the row numbers itself.

I hope this will help somebody with same or similar problem as mine!

Regards,

Julian

Upvotes: 2

andrewJames
andrewJames

Reputation: 22062

One approach is to use DataTables events to add and update a column of row numbers to your table. There are two aspects to this: (1) the initial rendering of the table; (2) subsequent re-draws for sorting and filtering.

For my demo, instead of using ajax, I will provide hard-coded data - but my approach should be compatible with your ajax approach.

The table:

 <table id="example" class="display dataTable cell-border" style="width:100%">
 </table>

My test data:

var dataSet = {
    "ChartData": {
        "FQCInLocalChart": [
            ["EM/AC.08.2.01", "Remote1"],
            ["EM/AD.08.2.01", "Remote2"],
            ["EM/AC.08.2.01", "Remote3"],
            ["EM/AC.08.2.03", "Remote2"]
        ]
    }
};

The dataTable code:

$(document).ready(function() {

    var table = $('#example').DataTable( {
      data: dataSet.ChartData.FQCInLocalChart,
      columns: [
        { title: "Name" },
        { title: "Status" }
      ],
      "initComplete": function() {
        addColNumbers();
      }
    } );

    table.on( 'draw', function () {
      rewriteColNumbers()
    } );

    function addColNumbers() {
      $('#example thead tr').prepend('<th>Num.</th>');
      $('#example tbody tr').each(function( index ) {
        $(this).prepend('<td>' + (index + 1) + '</td>');
      } );
    }

    function rewriteColNumbers() {
      $('#example tbody tr').each(function( index ) {
        $('td', this ).first().html(index + 1);
      } );
    }

} );

In the above approach, the initComplete() function handles the addition of a new column to the table.

And the table.on( 'draw' ) function captures subsequent re-draws for sorting/filtering.

The end result:

enter image description here

This approach means that the data in this new column is not visible to DataTables (it only gets added to the DOM) - and therefore does not take part in any sorting/filtering.

It also means the data would not be a part of any data export, if you use DataTables export add-ons.

You may want to add some styling/css to this new column, to control its width.

Upvotes: 1

Related Questions