异步填充的AngularJS ngTable使用JSON数据数据、AngularJS、ngTable、JSON

2023-09-13 04:06:01 作者:sincere(真心)

我想建立一个AngularJS应用程序,用于输出我使用JSON填充一个HTML表(该表的HTML是这个问题的底部)。我使用,我从我的服务器中检索应用程序/ JSON 数据。

当我做一个简单的卷曲的http://myurl.local/todo/api/v1/tasks ,我得到的,没有任何问题JSON。如果我把一个的console.log(); 此块中,我清楚地从服务器获取的JSON

 的getJSON:功能(){            VAR URL =HTTP://myurl.local/todo/api/v1/tasks';            VAR承诺= $ http.get(URL);            返回promise.then(功能(结果){                的console.log(拿到数据 - >中+ result.data);                返回result.data;            });        } 

我使用Chrome浏览器开发的应用程序;当我运行在Chrome应用程序,Chrome的JavaScript控制台抛出这个错误:类型错误:无法读取的未定义的属性长度之前,我到控制台.LOG(得到的数据 - >中+ result.data); 行。这是一个竞争条件。

该错误是很清楚在这里:

$ scope.tableParams =新ngTableParams({            页面:1,//显示第一页            数:10,//每页计        },{            总:数据&LT的data.length,//长度---破,需要一个承诺? 10分钟学会AngularJS的数据绑定

问题是,JavaScript是不是我的主要语言(这是蟒蛇);基础上的谷歌搜索,我对这个问题做了,我想我可以用在正确的地方的承诺/ 。然后()解决这个问题。不过我有困难的确切理解我应该怎么在我的JavaScript实现这一点。我想找到解决异步JSON GET的方式,并明白为什么需要做这样的。

有人能解释一下我应该怎么解决这个问题,我为什么要那样做?

的中的JavaScript 的:

VAR App2的= angular.module('taskTable',['ngRoute','ngTable']);    //需要使用瓶+神社时改变AngularJS符号    App2.config(函数($ interpolateProvider){        $ interpolateProvider.startSymbol('[[');        $ interpolateProvider.endSymbol(']');    });    //谢谢PeteBD    // http://stackoverflow.com/a/12513509/667301    //设置一个控制器来获得JSON的任务...    App2.factory('getTasks',函数($ HTTP){        返回{            的getJSON:功能(){                VAR URL =HTTP://myurl.local/todo/api/v1/tasks';                VAR承诺= $ http.get(URL);                返回promise.then(功能(结果){                    返回result.data;                });            }        }    });    App2.controller('tableCntl',函数($范围,getTasks,$过滤器,        ngTableParams){        VAR数据= [];        getTasks.getJson()。然后(功能(数据){            $ scope.data =数据;        });        数据= $ scope.data;        //设置任务表参数        $ scope.tableParams =新ngTableParams({            页面:1,//显示第一页            数:10,//每页计        },{            总:data.length,//数据的长度            的getData:函数($延迟,则params){                //使用内置的角度过滤器                VAR orderedData = params.filter()?                       $过滤器('过滤器')(数据,params.filter()):                       数据;                //存储过滤后的数据为$ scope.tasks                VAR = PAGECOUNT params.page();                变种paramCount = params.count();                $ scope.tasks = orderedData.slice((PAGECOUNT-1)* paramCount,                    * PAGECOUNT paramCount);                //设置为总重计算分页                params.total(orderedData.length);                $ defer.resolve($ scope.tasks);            }        });    });    //道具... angular.bootstrap()需要在同一页上,如果两个应用程序    // http://stackoverflow.com/a/18583329/667301    angular.bootstrap(的document.getElementById(任务),[taskTable]);

的 ngTable 的HTML表格:

< D​​IV ID =任务NG-应用=taskTableNG控制器=tableCntl>    < P><强大的过滤器过滤:LT; / STRONG> [tableParams.filter()| JSON]    <表NG表=tableParams显示过滤器=真正的类=表>        <&TBODY GT;          < TR NG重复=任务$数据>              < TD数据标题=说明排序=说明                  过滤器={说明:文本}>                  [[任务描述]]              < / TD>              < TD数据标题='优先级'排序=优先权                  过滤器={'优先':'文字'}>                  [task.priority]              < / TD>              < TD数据标题=输入排序=项>                  [task.entry]              < / TD>              < TD数据标题=状态排序=状态>                  [task.status]              < / TD>          < / TR>        < / TBODY>    < /表>  < / DIV>

解决方案

绝对值得看的 ngResource - 这将只是采取了所有的繁重你

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

  App2.factory('getTasks',函数($ HTTP){    返回{        的getJSON:功能(){            VAR URL =HTTP://myurl.local/todo/api/v1/tasks';            VAR承诺= $ http.get(URL);            返回promise.then(功能(结果){                返回result.data;            });        }    }}); 

我将其更改为:

  App2.factory('getTasks',函数($ HTTP){    返回{        的getJSON:功能(){            VAR URL =HTTP://myurl.local/todo/api/v1/tasks';            返回$ http.get(URL);        }    }}); 

由于$ HTTP返回的承诺。这意味着,此位仍然有效:

  getTasks.getJson()。然后(功能(数据){        $ scope.data =数据;    }); 

I'm trying to build an AngularJS app, which outputs an HTML table that I populate with json (the table's HTML is at the bottom of this question). I'm using application/json data that I retrieve from my server.

When I do a simple curl http://myurl.local/todo/api/v1/tasks, I get json with no problems. If I put a console.log(); inside this block, I'm clearly getting the json from the server.

        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;
            });
        }

I'm using Chrome to develop the app; when I run the app in Chrome, Chrome's javascript console throws this error: TypeError: Cannot read property 'length' of undefined before I get to that console.log("Got data ->" + result.data); line. It's a race condition.

The error is very clearly right here:

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

The problem is that javascript isn't my primary language (it's Python); based on the googling I've done about this problem, I think I could fix this with a promise / .then() in the right place. However I'm having difficulty understanding exactly how I should implement this in my javascript. I would like to find the way to fix the async json GET, and understand why it needs to be done that way.

Could someone explain how I should fix this, and why I should do it that way?

The 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"]);

The HTML table via 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>

解决方案

Definitely worth looking at ngResource - this will simply take out all the heavy lifting for you.

On another note, I suspect you don't need to do this:

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;
            });
        }
    }
});

i would change it to :

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

As $http returns the promise. That means this bit still works:

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