【问题标题】:asynchronously populating an AngularJS ngTable with json data使用 json 数据异步填充 AngularJS ngTable
【发布时间】:2014-03-12 11:09:29
【问题描述】:

我正在尝试构建一个 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);根据我对这个问题所做的谷歌搜索,我想我可以在正确的地方用一个 promise / .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>

【问题讨论】:

  • 嗨,这个语法是否正确:[[task.description]],你应该使用 {{ task.description}} 仪式,如果可能的话,在 jsfiddle.net 中发布
  • 嗨@MikePennington 您在此处显示的代码以及所有解决方案都运行良好?我得到未定义的数据,但如果我在 getTasks.getJson().then() 中记录数据,我会得到我期望的所有数据。是否有其他与这种方法相关的代码,关于用 JSON 数据异步填充 AngularJS ngTable?提前致谢。

标签: javascript json angularjs


【解决方案1】:

绝对值得一看 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;
    });

【讨论】:

  • 终于找到了剩下的问题...我不得不把$defer.resolve($scope.tasks);改成$defer.resolve(data);ngResource 确实简化了代码。
  • 酷!很高兴你把它整理好了!
猜你喜欢
  • 2018-05-29
  • 2018-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多