使用json数据异步填充AngularJS ngTable

时间:2014-03-12 11:09:30

标签: javascript json angularjs

我正在尝试构建一个AngularJS应用程序,它输出一个我用json填充的HTML表格(表格的HTML在这个问题的底部)。我正在使用从服务器检索的application/json数据。

当我做一个简单的curl http://myurl.local/todo/api/v1/tasks时,我得到了没有问题的json。如果我在这个块中放置一个console.log();,我显然是从服务器获取json。

        getJson: function() {
            var url = 'http://myurl.local/todo/api/v1/tasks';
            var promise = $http.get(url);
            return promise.then(function(result) {
                console.log("Got data ->" + result.data);
                return result.data;
            });
        }

我正在使用Chrome开发应用;当我在Chrome中运行该应用时,Chrome的javascript控制台会在我到达TypeError: Cannot read property 'length' of undefined行之前抛出此错误:console.log("Got data ->" + result.data);。这是竞争条件。

错误非常清楚:

        $scope.tableParams = new ngTableParams({
            page: 1,            // show first page
            count: 10,          // count per page
        }, {
            total: data.length, // length of data   <--- Broken, needs a promise?

问题是javascript不是我的主要语言(它是Python);根据谷歌搜索我对这个问题所做的,我想我可以在正确的地方用一个承诺/ .then()解决这个问题。但是我很难理解我应该如何在我的javascript中实现它。我想找到修复异步json GET的方法,并理解为什么需要这样做。

有人可以解释我应该如何解决这个问题,为什么我应该这样做呢?


JavaScript

    var App2 = angular.module('taskTable', ['ngRoute', 'ngTable']);
    // Need to change AngularJS symbols when using flask + Jinja
    App2.config(function($interpolateProvider) {
        $interpolateProvider.startSymbol('[[');
        $interpolateProvider.endSymbol(']]');
    });

    // Thank you PeteBD
    //     http://stackoverflow.com/a/12513509/667301
    // Set up a controller to get json tasks...
    App2.factory('getTasks', function($http) {
        return {
            getJson: function() {
                var url = 'http://myurl.local/todo/api/v1/tasks';
                var promise = $http.get(url);
                return promise.then(function(result) {
                    return result.data;
                });
            }
        }
    });
    App2.controller('tableCntl', function($scope, getTasks, $filter, 
        ngTableParams) {

        var data = [];
        getTasks.getJson().then(function(data) {
            $scope.data = data;
        });
        data = $scope.data;
        // Set up task table parameters
        $scope.tableParams = new ngTableParams({
            page: 1,            // show first page
            count: 10,          // count per page
        }, {
            total: data.length, // length of data
            getData: function($defer, params) {
                // use build-in angular filter
                var orderedData = params.filter() ?
                       $filter('filter')(data, params.filter()) :
                       data;
                // store filtered data as $scope.tasks
                var pageCount = params.page();
                var paramCount = params.count();
                $scope.tasks = orderedData.slice((pageCount-1)*paramCount, 
                    pageCount*paramCount);
                // set total for recalc pagination
                params.total(orderedData.length);
                $defer.resolve($scope.tasks);
            }
        });
    });
    // Props... angular.bootstrap() is required if two apps on the same page
    // http://stackoverflow.com/a/18583329/667301
    angular.bootstrap(document.getElementById("Tasks"),["taskTable"]);

HTML表格通过ngTable

  <div id="Tasks" ng-app="taskTable" ng-controller="tableCntl">
    <p><strong>Filter:</strong> [[tableParams.filter()|json]]
    <table ng-table="tableParams" show-filter="true" class="table">
        <tbody>
          <tr ng-repeat="task in $data">
              <td data-title="'Description'" sortable="description" 
                  filter="{'description': 'text'}">
                  [[task.description]]
              </td>
              <td data-title="'Priority'" sortable="priority" 
                  filter="{'priority': 'text'}">
                  [[task.priority]]
              </td>
              <td data-title="'Entered'" sortable="entry">
                  [[task.entry]]
              </td>
              <td data-title="'Status'" sortable="status">
                  [[task.status]]
              </td>
          </tr>
        </tbody>
    </table>
  </div>

1 个答案:

答案 0 :(得分:3)

绝对值得一看ngResource - 这将为您解决所有繁重的工作。

另一方面,我怀疑你不需要这样做:

App2.factory('getTasks', function($http) {
    return {
        getJson: function() {
            var url = 'http://myurl.local/todo/api/v1/tasks';
            var promise = $http.get(url);
            return promise.then(function(result) {
                return result.data;
            });
        }
    }
});

我会将其更改为:

 App2.factory('getTasks', function($http) {
    return {
        getJson: function() {
            var url = 'http://myurl.local/todo/api/v1/tasks';
            return $http.get(url);
        }
    }
});

$ http返回承诺。这意味着这一点仍然有效:

    getTasks.getJson().then(function(data) {
        $scope.data = data;
    });