Search code examples
angularjsdatatablesangular-datatablesbootstrap-accordion

DataTables inside bootstrap accordion in angularjs


I am working on a module where I have to redesign some products. Following is the screenshot of how the products used to get displayed previously.

enter image description here

Now the products will be displayed inside accordion of their specific name. I am bound to use ui.bootstrap Version: 0.11.0 - 2014-05-01. Following is a sketch of how the products will be displayed now. In each accordion there will be a datatable of that particular product in which the columns will dynamically generate and we would be able to check the particular products we want.

enter image description here

Following is my html code:

                <accordion>
                    <accordion-group ng-repeat="AllProduct in AllProducts">
                        <accordion-heading>
                            {{AllProduct.TypeName}}
                           </accordion-heading>

                    </accordion-group>
                    <table id="dtVoice" class="table manage-user-table offer-mgt-table" dt-options="dtOptions" dt-columns="dtColumns"></table>
                </accordion>

The way i have dynamically created datatables are as follows:

 dtColumns.push(DTColumnBuilder.newColumn(null).withTitle('').notSortable()
          .renderWith(function(data, type, full, meta) {
              return '<input type="checkbox" ng-model="showCase.selected[' + data.id + ']"/>';
          }));

        for (var key in $scope.VoiceProducts[0]) {
            if (key == "ProductName" || key == "LongDistanceMinutes" || key == "IsCallWaiting") {
                dtColumns.push(
                  DTColumnBuilder.newColumn(key).withTitle(key)

                )
            }

            $scope.dtColumns = dtColumns;
            $scope.dtOptions = DTOptionsBuilder.newOptions()
              .withOption('data', $scope.VoiceProducts)
              .withOption('dataSrc', '')


            angular.element('#dtVoice').attr('datatable', '')
        }
       $compile(angular.element('#dtVoice'))($scope);

Following is my json

 [
  {
    "ProductList": [
      {
        "ProductName": "Voice",
        "IsActive": false,
        "IsDeleted": false,
        "LongDistanceMinutes": "",
        "IsCallWaiting": "",
        "CallWaitingId": "",
        "IsThreeWayCalling": "",
        "IsCallerId": "",
        "IsCallForwarding": "",
        "IsCallRejection": "",
        "ID": 552,
        "OfferId": 0
      }
    ],
    "ID": 2,
    "IsActive": false,
    "IsDeleted": false,
    "TypeName": "Voice"
  }
]

How to put this datatable inside accordion? Because by doing whatever I'm, i'm unable to achieve it.


Solution

  • UPDATED: As per new information (using angular-datatable)

    The solution now boils down to computing the columns and options per accordion-group.

    Working Plunker with 2 accordion groups

    As you can see in the HTML below the options and columns are computed per accordion.

    <table datatable class="table manage-user-table offer-mgt-table"  dt-options="getDtOptions(AllProduct)" dt-columns="getDtColumns(AllProduct)"></table>
    

    Angular code showing getDtColumns and getDtOptions. I have kept the data very simple for demonstration purposes and copied the current dtColumns code however you can customize it so that you can even have more than 1 type of table :

    var app = angular.module('myApp', ['ui.bootstrap', 'datatables']);
    app.controller('myCtrl', function($scope, DTColumnBuilder, DTOptionsBuilder, DTColumnDefBuilder, $timeout, AllProducts) {
      $scope.AllProducts = AllProducts
    
    
      $scope.getDtColumns = function(allProduct) {
        var items = allProduct.ProductList;
        if (allProduct.dtColumns) allProduct.dtColumns.length = 0;
        allProduct.dtColumns =  allProduct.dtColumns || [];
        var dtColumns = allProduct.dtColumns;
        dtColumns.push(DTColumnBuilder.newColumn('').withTitle('').notSortable()
          .renderWith(function(data, type, full, meta) {
            return '<input type="checkbox" ng-model="showCase.selected[' + full.id + ']"/>';
          }));
    
    
        for (var key in items[0]) {
          if (key == "ProductName" || key == "LongDistanceMinutes" || key == "IsCallWaiting") {
            dtColumns.push(
              DTColumnBuilder.newColumn(key).withTitle(key).notSortable()
            )
          }
        }
    
        return dtColumns;
      };
    
      $scope.getDtOptions = function(allProduct) {
        if (allProduct.options) return allProduct.options;
        var items = allProduct.ProductList;
        allProduct.options = allProduct.options || DTOptionsBuilder.newOptions().withOption('aaData', items);
        return allProduct.options;     
      };
    
    
    });
    

    OLDER ANSWER without angular-datatable

    First of all I do not recommend jQuery DataTable or any other jQuery component in AngularJS applications. I personally try not to bundle jQuery or perform DOM manipulation using jQuery.

    However to get you going with what you have I suggest the following:-

    Remove these two lines because simply adding those attributes datatable dynamically is not going to trigger the DataTable binding:-

    angular.element('#dtVoice').attr('datatable', '')
            }
           $compile(angular.element('#dtVoice'))($scope);
    

    and try using something like this:-

    $('#dtVoice').DataTable( {columnDefs: $scope.dtColumns });

    Further more just to clean up a bit I create a new directive (just typing out loud):

    app.directive('myDatatable`, function(){
    return {
       restrict: 'A',
       scope: {
           'dtColumns': '='
       }
       link: function($scope, elem, attr) {
            $('#dtVoice').DataTable( {columnDefs: $scope.dtColumns});    
       } 
    };
    });
    

    and your table something like below:

    <table id="dtVoice" 
        class="table manage-user-table offer-mgt-table" 
          dt-options="dtOptions" 
          dt-columns="dtColumns" my-datatable></table>