Friday, May 10, 2024
 Popular · Latest · Hot · Upcoming
-2
rated 0 times [  5] [ 7]  / answers: 1 / hits: 5929  / 10 Years ago, wed, march 12, 2014, 12:00:00

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>

More From » json

 Answers
4

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

[#46928] Tuesday, March 11, 2014, 10 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
kaitlynnb

Total Points: 402
Total Questions: 96
Total Answers: 109

Location: Trinidad and Tobago
Member since Fri, May 8, 2020
4 Years ago
kaitlynnb questions
;