crowz
crowz

Reputation: 108

Angularjs expandable table row

I am using angular 1.4.3 and angular dataTables (here's the link: http://l-lin.github.io/angular-datatables).

My needs is basic. I need to expand the row when it is clicked and all the ng-click's or the others need to work. But in the docs of library they fires the callback like this;

https://datatables.net/examples/api/row_details.html

when I try to add a button that has ng-click to that format function in the example. It doesn't work (I mean ng-click does not work.). I think the problem accurs because of the element appends to table after the document load.

Do you habve any idea about it?

Upvotes: 2

Views: 6441

Answers (1)

davidkonrad
davidkonrad

Reputation: 85578

You are right, ng-click has to be $compile'd before it is any good. But you do not have to go all the angular way : Since dataTables is a jQuery plugin you can still use delegated event handlers and so on - the biggest problem is to access the API, fortunetaly we can use the dtInstance instead. Here is a angular-datatables version of the infamous Child rows example :

Markup :

<table datatable="" dt-options="dtOptions" dt-columns="dtColumns" dt-instance="dtInstance"></table>

Basic initialisation, use a remote JSON source (notice .details-control is set here):

$scope.dtColumns = [
  DTColumnBuilder.newColumn('name').withTitle('Name')
                                   .withOption('className', 'details-control'),
  DTColumnBuilder.newColumn('position').withTitle('Position'),
  DTColumnBuilder.newColumn('salary').withTitle('salary')
];  

$scope.dtInstance = {};

$scope.dtOptions = DTOptionsBuilder
  .fromSource('https://api.myjson.com/bins/2v7sr')
  .withPaginationType('full_numbers')
  .withDataProp('data');

"Child rows" example ported so it works in angular :

var format = function ( d ) {
    // `d` is the original data object for the row
    return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+
        '<tr>'+
           '<td>Full name:</td>'+
           '<td>'+d.name+'</td>'+
        '</tr>'+
        '<tr>'+
           '<td>Extension number:</td>'+
           '<td>'+d.extn+'</td>'+
        '</tr>'+
        '<tr>'+
           '<td>Extra info:</td>'+
           '<td>And any further details here (images etc)...</td>'+
         '</tr>'+
        '</table>';
}

$('body').on('click', '.details-control', function() {
   var tr = $(this).closest('tr');
   var row = $scope.dtInstance.DataTable.row( tr );
   if ( row.child.isShown() ) {
      // This row is already open - close it
      row.child.hide();
      tr.removeClass('shown');
   } else {
      // Open this row
      row.child( format(row.data()) ).show();
      tr.addClass('shown');
   }
})  

Basically it is the same, just listening on body as parent element for the delegation, using dtInstance instead of a dataTable API instance.

demo -> http://plnkr.co/edit/0CA9jMIg4gXqj9fnY38p?p=preview

Upvotes: 3

Related Questions