Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add columns to dynamic ng-table based on results of promise

I've been using the ngTableDynamic directive recently and it works great when I know exactly what columns my table should expect. However, I'm running into issues when my table is truly dynamic and I do not know in advance the number or type of columns to expect.

At the top of my controller I declare the columns I know will be present in every table:

$scope.columns = [
  { title: 'ID', field: 'id', visible: true, required: true },
  { title: 'Email', field: 'email', visible: true, required: true }
];

I then make an asynchronous call to a service which returns results. Based on these results I push any additional column objects into $scope.columns:

var getResults = function() {
  var defer = $q.defer();
  reportService.getReportResults({
    report: $scope.id,
    version: $scope.version
  }).$promise.then(function(data) {
    $scope.data = data.results;
    _.each($scope.data[0], function(value, key) {
      if (key !== 'id' && key !== 'email') {
        $scope.columns.push({
          title: _str.capitalize(key),
          field: key,
          visible: true,
          required: false
        });
      }
    });
    defer.resolve($scope.data);
  });
  return defer.promise;
};

However, the columns pushed within _.each never make it to my table when I view it in the browser. If I replace my asynchronous call with a hard-coded mock of an example set of data however, the columns are added and everything works as expected:

var getResults = function() {
  var defer = $q.defer();
  $scope.data = [{"id":"1","email":"[email protected]",,"create_date":"2013-09-03T09:00:00.000Z"},{"id":"2","email":"[email protected]","create_date":"2013-09-03T11:10:00.000Z"}];
  _.each($scope.data[0], function(value, key) {
    if (key !== 'id' && key !== 'email') {
      $scope.columns.push({
        title: _str.capitalize(key),
        field: key,
        visible: true,
        required: false
      });
    }
  });
  defer.resolve($scope.data);
  return defer.promise;
};

Further down in my controller my init code calls

getResults().then(function() {
  $scope.tableParams.reload();
});

$scope.tableParams = new ngTableParams({...

My assumption is that as soon as the promise is resolved $scope.tableParams.reload(); is called before $scope.columns is updated.

like image 768
MattDionis Avatar asked Oct 19 '22 05:10

MattDionis


1 Answers

Based on demo from documentation it was quite is to make example with promises. It just seems that you have to create new tableParams and cols object after getting response from promise. Adding rows to existing cols may not trigger watcher.

angular.module('app', ['ngTable']);

angular.module('app').controller('Demo', function($scope, NgTableParams, dataService) {
  $scope.cols = [{
    title: 'ID',
    field: 'id',
    visible: true
  }, {
    title: 'Email',
    field: 'email',
    visible: true
  }, {
    title: 'Create Date',
    field: 'create_date',
    visible: true
  }];
  
  dataService
    .getData()
    .then(function (response) {
      $scope.tableParams = new NgTableParams({}, {
        dataset: response.results
      });
      $scope.cols = $scope.cols.concat(response.cols);
    });
});

angular.module('app').factory('dataService', function($timeout) {
  return {
    getData: function() {
      return $timeout(function() {
        var n = Math.round(Math.random() * 50) + 5;
        var results = [];

        for (var i = 0; i < n; i++) {
          results.push({
            id: Math.random(),
            email: 'ex' + Math.random() + '@example.com',
            create_date: new Date(),
            x: Math.round(Math.random() * 10),
            y: Math.round(Math.random() * 25)
          });
        }

        return {
          results: results,
          cols: [
            {
              title: 'X',
              field: 'x',
              visible: true
            },
            {
              title: 'Y',
              field: 'y',
              visible: true
            }
          ]
        };
      }, 500);
    }
  };
});
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.2/angular.js"></script>
<link rel="stylesheet" href="https://rawgit.com/esvit/ng-table/master/dist/ng-table.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="https://rawgit.com/esvit/ng-table/master/dist/ng-table.min.js"></script>

<div ng-app="app" ng-controller="Demo">
  <table ng-table-dynamic="tableParams with cols" class="table table-condensed table-bordered table-striped">
    <tr ng-repeat="row in $data">
      <td ng-repeat="col in $columns">{{row[col.field]}}</td>
    </tr>
  </table>
</div>
like image 164
sielakos Avatar answered Oct 21 '22 01:10

sielakos