根据promise的结果将列添加到动态ng-table

时间:2016-07-17 12:32:55

标签: javascript angularjs ngtable

我最近一直在使用ngTableDynamic指令,当我确切地知道我的表应该期望哪些列时,它会很有效。但是,当我的表格真正动态并且我事先并不知道期望的列数或类型时,我遇到了问题。

在我的控制器顶部,我声明我知道的列将出现在每个表中:

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

然后我对一个返回结果的服务进行异步调用。根据这些结果,我将任何其他列对象推送到$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;
};

但是,当我在浏览器中查看时,_.each内推送的列永远不会进入我的表。如果我用一组示例数据的硬编码模拟替换我的异步调用,则添加列并且一切都按预期工作:

var getResults = function() {
  var defer = $q.defer();
  $scope.data = [{"id":"1","email":"test@sample.com",,"create_date":"2013-09-03T09:00:00.000Z"},{"id":"2","email":"sample@test.org","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;
};

在我的控制器中,我的初始化代码调用

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

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

我的假设是,一旦承诺得到解决,$scope.tableParams.reload();会在$scope.columns更新之前被调用。

3 个答案:

答案 0 :(得分:2)

根据文档中的demo,我们就是以promises为例。 看来你必须在从promise获得响应后创建新的tableParams和cols对象。向现有cols添加行可能不会触发观察者。



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);
    }
  };
});
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

原因是您将数据异步应用于$ scope(在promise中然后阻止),因此您不在角度摘要周期内,并且您的表将不会更新。

这在您的模拟中不会发生,因为您同步设置了$ scope.data。 (A more detailed explanation can be found here

要解决此问题,您应该通过angular通知您已使用$ scope对范围进行了一些更改。$ digest()

我发现您的代码存在其他一些问题,我将尝试解决这个问题

  • 承诺的使用不当(读:尽可能避免'延迟')
  • 没有功能性方法
  • 对一般的承诺/角度有点困惑

足够的喋喋不休,这就是我写同样功能的方式:

IEquatable<MatchItem>

答案 2 :(得分:0)

尝试

var getResults = function() {
  var defer = $q.defer();
  reportService.getReportResults({
    report: $scope.id,
    version: $scope.version
  }).$promise.then(defer.resolve);
  return defer.promise;
};


 getResults().then(function(_data) {
 $scope.data = _data;
 _.each($scope.data, function(value, key) {
      if (key !== 'id' && key !== 'email') {
        $scope.columns.push({
          title: _str.capitalize(key),
          field: key,
          visible: true,
          required: false
        });
      }
    });

 });

或直接在控制器中

    reportService.getReportResults({
    report: $scope.id,
    version: $scope.version
  }).then(function(_data) {
     $scope.data = _data;
     _.each($scope.data, function(value, key) {
          if (key !== 'id' && key !== 'email') {
            $scope.columns.push({
              title: _str.capitalize(key),
              field: key,
              visible: true,
              required: false
            });
          }
        });

     });