Able to fetch data but unable to display it in table - angularjs

Code:
var app = angular.module('myApp', ['smart-table']);
app.controller("MyController", function ($scope, $http) {
$scope.get = function ()
{
$http.get('JsonProcessor.do').
success(function (data, status, headers, config)
{
$scope.rowCollection = data[0];
console.log("Result from Database: ", data[0]); //prints value
console.log(data[0].ID); //prints ID
}).
error(function (data, status, headers, config)
{
});
};
});
I am able to fetch data and display it in console but I wonder its not displayed inside table.
However, ng-repeat creates four rows in table but with no data
Html:
<table st-table="rowCollection" class="table table-striped">
<thead>
<tr>
<th>Unique Id</th>
<th>Date Created</th>
<th>Doc Url</th>
<th>Time Stamp</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rowCollection">
<td>{{row.ID}}</td>
<td>{{row.DATE_CREATED}}</td>
<td>{{row.URL}}</td>
<td>{{row.TIMESTAMP}}</td>
</tr>
</tbody>
</table>
What could be the issue?

Since your data is coming from a service call you must use st-safe-src for smart table.
http://lorenzofox3.github.io/smart-table-website/
stSafeSrc attribute
"If you are bringing in data asynchronously (from a remote database, restful endpoint, ajax call, etc) you must use the stSafeSrc attribute. You must use a seperate collection for both the base and safe collections or you may end up with an infinite loop."

Related

Unable to bind Json Data with Table Header using AngularJS

Im getting data in this format from api, but when i try binding it to table using angularjs it is creating empty space instead of values. Im also getting more then one table from some Api's please explain who to bind different datatables in different tables too. thanks
{"Table":
[{
"SchoolId":1,
"schoolname":"Microsoft",
"SCHOOLCODE":"29911583",
"WEBSITE":"JLR",
"USEREMAIL":"faucibus#aliquamiaculislacus.org",
"PHONE":"841-9331",
"ADDRESS1":"682-5760 Felis Street",
"ISACTIVE":0,
"PLANTYPE":3
}]
}
Angular Controller
SMSApp.factory('GetStudentService', function ($http) {
studobj = {};
studobj.getAll = function () {
var stud=[];
stud = $http({ method: 'Get', url: 'http://localhost:58545/api/Student?Studentid=1' }).
then(function (response) {
return response.data;
});
return stud;
};
return studobj;
});
SMSApp.controller('studentController', function ($scope, GetStudentService) {
$scope.msg = "Welcome from Controller";
GetStudentService.getAll().then(function (result) {
$scope.school = result;
console.log(result);
});
});
HTML Code
<tbody ng-controller="studentController">
<tr ng-repeat="schools in school track by $index">
<td>{{schools.SchoolId}}</td>
<td>{{schools.schoolname}}</td>
<td>{{schools.SCHOOLCODE}}</td>
<td>{{schools.WEBSITE}}</td>
<td>{{schools.USEREMAIL}}</td>
</tr>
</tbody>
WHAT I GET
Change in your Angular Controller :
SMSApp.controller('studentController', function ($scope, GetStudentService) {
$scope.msg = "Welcome from Controller";
GetStudentService.getAll().then(function (result) {
/********************* Changed Here ********************/
$scope.school = JSON.parse(result._body); // Or only JSON.parse(result)
$scope.school = $scope.school.table;
});
});
And your HTML Code :
<tbody ng-controller="studentController">
<tr ng-repeat="schools in school track by $index">
<td>{{schools.SchoolId}}</td>
<td>{{schools.schoolname}}</td>
<td>{{schools.SCHOOLCODE}}</td>
<td>{{schools.WEBSITE}}</td>
<td>{{schools.USEREMAIL}}</td>
</tr>
</tbody>
Naming the data school is confusing. Do instead:
GetStudentService.getAll().then(function (data) {
$scope.tableObj = data;
console.log(data);
});
<tbody ng-controller="studentController">
<tr ng-repeat="school in tableObj.Table track by school.SchoolId">
<td>{{school.SchoolId}}</td>
<td>{{school.schoolname}}</td>
<td>{{school.SCHOOLCODE}}</td>
<td>{{school.WEBSITE}}</td>
<td>{{school.USEREMAIL}}</td>
</tr>
</tbody>
From the Docs:
Best Practice: If you are working with objects that have a unique identifier property, you should track by this identifier instead of the object instance, e.g. item in items track by item.id. Should you reload your data later, ngRepeat will not have to rebuild the DOM elements for items it has already rendered, even if the JavaScript objects in the collection have been substituted for new ones. For large collections, this significantly improves rendering performance.
— AngularJS ng-repeat API Reference
Just replace your result with result.Table in your controller because if you properly see your response it is inside "Table" named array. Try this you should be able to see your records
SMSApp.controller('studentController', function ($scope, GetStudentService) {
$scope.msg = "Welcome from Controller";
GetStudentService.getAll().then(function (result) {
$scope.school = result.Table;
console.log(result);
});
});
Note: I have replaced your API call in the jsfiddle link with the response mentioned in the question.
JSFiddle Link : http://jsfiddle.net/zu8q7go6/9/

Do a loop instead of multiple $http chaining?

sorry, i have checked answers, but still dont understand how to make it :
I've got an array :
var surfaces = [
{min:0,max:499},
{min:500,max:999},
{min:1000,max:1499},
{min:1500,max:1999},
{min:2000,max:2399},
{min:2400,max:2999},
{min:3000,max:3999},
{min:4000,max:5999},
{min:6000,max:100000}
]
And I've got this looong $http chained calls with $q :
$q.when()
.then(function () {
$http.post('backend/backend.php?action=get_normes',surfaces[0]).success(function(data){
$scope.normes.push(data);
})
})
.then(function () {
$http.post('backend/backend.php?action=get_normes',surfaces[1]).success(function(data){
$scope.normes.push(data);
})
})
.then(function () {
$http.post('backend/backend.php?action=get_normes',surfaces[2]).success(function(data){
$scope.normes.push(data);
})
})
.then(function () {
$http.post('backend/backend.php?action=get_normes',surfaces[3]).success(function(data){
$scope.normes.push(data);
})
})
.then(function () {
$http.post('backend/backend.php?action=get_normes',surfaces[4]).success(function(data){
$scope.normes.push(data);
})
})
.then(function () {
$http.post('backend/backend.php?action=get_normes',surfaces[5]).success(function(data){
$scope.normes.push(data);
})
})
.then(function () {
$http.post('backend/backend.php?action=get_normes',surfaces[6]).success(function(data){
$scope.normes.push(data);
})
})
.then(function () {
$http.post('backend/backend.php?action=get_normes',surfaces[7]).success(function(data){
$scope.normes.push(data);
})
})
.then(function () {
$http.post('backend/backend.php?action=get_normes',surfaces[8]).success(function(data){
$scope.normes.push(data);
})
})
I'd rather do a loop, but have now idea on how to do this !!
EDIT : I've got way bigger problem : data is not in order in $scope.normes ! Its always different ! How could i do to always push in order ? How could the data could be in order ?
I got ng-repeats like this but the information is not well ordered because of $http synchornicity ;
<div class="row ">
<div class="col-lg-10" style="overflow: auto; max-height: 600px;">
<table class="table table-bordered table-hover " border="1" >
<thead >
<tr>
<th> Désignation</th>
<th> Total Magasins</th>
<th> Moy Habitants Zone</th>
<th> Ca Moyen</th>
<th> EO Mini</th>
<th> EO Maxi</th>
<th> Coef Moyen</th>
<th> Pourcent Côtier</th>
<th> Pourcent Urbain</th>
<th> Tx Habituels</th>
<th> Tx fréquentation</th>
<th> Tx fidélisation</th>
<th> Zone Attraction</th>
<th> Revenus Zone</th>
<th> Nb Perso Foyer</th>
<th> Age Moyen</th>
</tr>
</thead>
<tbody >
<tr ng-repeat="norme in normes" >
<td>Surface 0-499 m²</td>
<td>{{::norme.nb_magasins | number:0}}</td>
<td>{{::norme.moy_habitants_zone | number:0}}</td>
<td>{{::norme.ca_moyen | number:0}}</td>
<td>{{::norme.eomin | number:0}}</td>
<td>{{::norme.eomax | number:0}}</td>
<td>{{::norme.coef_moyen | number:2}}</td>
<td></td>
<td></td>
<td>{{::norme.tx_habituels | number:2}}</td>
<td>{{::norme.tx_frequentation | number:2}}</td>
<td>{{::norme.tx_fidelisation | number:2}}</td>
<td>{{::norme.attraction | number:0}}</td>
<td>{{::norme.revenus_zone | number:0}}</td>
<td>{{::norme.nb_pers_foyer | number:2}}</td>
<td>{{::norme.age_moyen | number:2}}</td>
<td ></td>
</tr>
</tbody>
</table>
</div>
Each time i redo the $q, it comes with a different order ! How could i do ?
EDIT : So I'm now getting standards JSON objects from the Back End so it is simplier(Editied the html table on this post), but with the solutions you gently provided, it doesnt appear yet in the right order. The $http get started in the right order, but it seems that $scope.normes doesnt list as the $http have been started ! (Oh i think i maybe can order with the orderby in the front end... I forgot, but i thought it was possible to order the json objects as they get pushed into the array, but in the view it doesnt appear as when the $http have been called)
Try this::
$scope.onAllDone = function() {
var promises = [];
angular.forEach(surfaces , function(surface) {
promises.push($http.post('backend/backend.php?action=get_normes',surface)).then(function(data) {
$scope.normes.push(data);
return data;
});
});
return $q.all(promises);
}
USE::
$scope.onAllDone().then(fnSuccess, fnError);
Promises and $q.all (doc) are your friends.
In more detail, you will have to make a promise for each call (if the call itself does not return one), push them in an array and call $q.all(promises).then(allFinished).
function callUpdate(x, promises) {
var d = $q.defer();
$http.post('backend/backend.php?action=get_normes',x).then(function(resp){
$scope.normes.push(resp.data);
d.resolve(resp.data);
})
promises.push(d.promise);
}
...
var promises = [];
$scope.normes = [];
for (var i = 0; i < surfaces.length; i++) {
callUpdate(surfaces[i], promises);
}
$q.all(promises).then(function() {
// called when all promises have been resolved successully
});
Create an array of promises
var promises = [];
surfaces.forEach(function(surface){
promises.push($http.post('backend/backend.php?action=get_normes',surface));
})
You can use $q.all() and wait for all promises to complete and use Array.concat() to create $scope.normes array.
$q.all(promises).then(function (results) {
$scope.normes = [].concat.apply([],results);
});
When chaining promises, it is important to return the subsequent promise to the .then method handler function:
var arrayPromise = $q.when([])
.then(function (dArray) {
var httpPromise = $http.post('backend/backend.php/action=get_normes',surfaces[0])
var dPromise = httpPromise.then(function(response) {
$scope.normes.push(response.data);
dArray.push(response.data);
return dArray;
});
return dPromise;
}).then(function(dArray) {
console.log("one XHR is complete");
console.log(dArray);
});
When the code fails to return anything to the handler function, the $q service resolves the promise as undefined and immediately executes the next function. By returning the subsequent promise, the $q service will wait for the promise to resolve before executing the next promise in the chain.
That said. How to create a loop that chains sequential promises?
var arrayPromise = $q.when([]);
for (let n=0; n<surfaces.length; i++) {
arrayPromise = arrayPromise
.then(function (dArray) {
var httpPromise = $http.post(url,surfaces[n]);
var dPromise = httpPromise.then(function(response) {
$scope.normes.push(response.data);
dArray.push(response.data);
//return dArray to chain
return dArray;
});
return dPromise;
});
};
arrayPromise.then(function(dArray) {
console.log("all XHRs are complete");
console.log(dArray);
}).catch(function(errorResponse) {
console.log("one of the XHRs failed");
console.log(errorResponse.status);
throw errorResponse;
});
Create a variable with a promise for an empty array. Then in the loop simply assign the promise derived from the .then method back to that variable. Each iteration of the loop returns an array that is one item larger than the previous iteration. Also each iteration has the side effect of pushing an item to scope.

Not fetching data with Angular JS

I'm trying to build an app with Angular JS that fetches data from a Django REST API.
I have this script
var userListApp = angular.module('userListApp', ['ngResource']);
userListApp.factory('Classroom', function($resource) {
return $resource('/classrooms/:id/',
{'query': {method: 'GET', isArray:false}}
);
});
userListApp.controller('UsersController', function($scope, Classroom) {
Classroom.query(function(data) {
$scope.classrooms = data;
});
});
and this is the html
<div ng-app="userListApp">
<div ng-controller="UsersController">
<table class="table table-striped">
<thead>
<tr>
<th>Classroom</th>
<th>School</th>
<th>Academic year</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="classroom in classrooms">
<td>{{classroom.classroom}}</td>
<td>{{classroom.school}}</td>
<td>{{classroom.academic_year}}</td>
</tr>
</tbody>
</table>
</div>
</div>
But I'm getting this error in the console
Error: $resource:badcfg
Response does not match configured parameter
Error in resource configuration for action query. Expected response to contain an array but got an object (Request: GET /classrooms)
(from the error reference page of Angular JS)
I was looking at some answers here on stackoverflow, and came to this one, and I tried to do what they say
userListApp.factory('Classroom', function($resource) {
return $resource('/classrooms/:id/',
{method: 'classrooms', id: '*'},
{'query': {method: 'GET', isArray:false}}
);
});
And I'm getting no error, but no data either. There are, however, some tables on the webpage, like if it's trying to "catch" something, here's a screenshot
UPDATE:
I've tried to put this line
return $resource('/classrooms/?format=json',
Instead of this
return $resource('/classrooms/:id/',
on the Angular app, and there's no data, but, if I go to developer tools on Network -> XHR, I get the json data
[{"school":{"id":1,"school_name":"IPSIA F. Lampertico","address":"Viale Giangiorgio Trissino, 30","city":"Vicenza"},"academic_year":"2015/2016","classroom":"1^A","floor":0,"students":[{"classroom":1,"first_name":"Stefano","last_name":"Rossi","gender":"M","birthday":"1998-06-22"},{"classroom":1,"first_name":"Luca","last_name":"Possanzini","gender":"M","birthday":"1999-11-22"}]
but, as I said, that data is not shown on the tables in the html.
UPDATE 2:
After adding "?format=json'" to the resource url, I get the exact amount of rows (in my data I have three classrooms, so I get three rows in the HTML table), but no data in it.
UPDATE 3:
I've added this line to debug the code
userListApp.controller('UsersController', function($scope, Classroom) {
Classroom.query(function(data) {
$scope.classrooms = data;
console.log(data); <--- NEW LINE FOR THE DEBUG
});
});
and now I get this, on the console log
Your data is not in the correct format. The data you posted has missing }] in the end. Recheck your server response.
I replicated the whole scenario on my machine and your code worked perfectly fine.
HTML: Same as yours.
Script:
var userListApp = angular.module('userListApp', ['ngResource']);
userListApp.factory('Classroom', function($resource) {
return $resource('http://localhost:9000/classrooms/1', //changed this line only.
{'query': {method: 'GET', isArray:false}}
);
});
userListApp.controller('UsersController', function($scope, Classroom) {
Classroom.query(function(data) {
$scope.classrooms = data;
});
});
http://localhost:9000/classrooms/1 returns just the data that you specified with }] appended at the end.
OUTPUT:

How to echo JSON array as Smart Table data with Angluarjs

I'm pretty new to Angular, and trying to build a table using Smart Table based on data I'm fetching from a REST api. I can build the table fine with manually entered data, but when I try to insert a JSON array of data from the server the resulting table is empty.
Currently I have the following set up:
dataFactory.js - calls the API and gets a JSON response:
app.factory('dataFactory', ['$http', function($http) {
var urlBase = 'http://myurl.com/api';
var dataFactory = {};
dataFactory.getOrders = function() {
return $http.get(urlBase + '/orders');
};
return dataFactory;
}]);
My view is fairly basic and looks like this using to the Smart Table extension:
<div ng-controller="MainController">
<table st-table="ordersTable" class="table table-striped">
<thead>
<tr>
<th st-sort="createdBy">Name</th>
<th st-sort="id">ID</th>
<th st-sort="state">State</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in ordersTable">
<td>{{row.createdBy}}</td>
<td>{{row.id}}</td>
<td>{{row.state}}</td>
</tr>
</tbody>
</table>
</div>
And my MainController.js processes and stores the data, and builds the table:
app.controller('MainController', ['$scope', 'dataFactory', function($scope, dataFactory) {
$scope.status;
$scope.orders;
getOrders();
function getOrders() {
dataFactory.getOrders()
.success(function(ord) {
$scope.orders = ord;
})
.error(function(error) {
$scope.status = 'Unable to load order data: ' + error.message;
});
}
$scope.ordersTable = [
// If I build the data manually the table builds using the following 3 lines
//{createdBy: 'Laurent', id: '56433', state: 'Open')},
//{createdBy: 'Blandine', id: '34367', state: 'Open')},
//{createdBy: 'Francoise', id: '34566', state: 'Closed'}
//... however I actually want the data to come from the JSON array returned by my factory like this:
$scope.orders
];
}]);
What am I doing wrong? How can I get my data to show up in the table?
In the success callback you are updating $scope.orders and not $scope.orderTable. By the way use promise function then instead of success and error callback (extract from angularjs doc):
The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.

ASP.Net WEB API AND ANGULAR Not outputting one column vs another

I was able to set up a asp.net web api and scaffolding to my sql server database. The return of the records from sql server appears to be JSON. The model has a few tables linked to each other by foreign keys and only has 2 records right now. Comp_Id = 1 and 2. The results to my local api looks like this:
[{"ASSOC_INC_OFF":[{"OFFICERINVOLVEDs":[],"AIO_ID":1,"COMP_ID":1,"OFCNUM":1,"LINK_TYPE":null}],"CRITICALINCIDENTs":[{"CIType":"Physical Force resulting in Death or Serious Bodily Injury","CINotice":null,"CIMonitorRolledOut1":null,"CIDAMonitored":null,"CIOIMQuestions":null,"CICharged":null,"CIMonitor1":null,"CIMonitor2":null,"CINotes":null,"CIOfcCharges":null,"CIOutcome":null,"COMP_ID":1,"RolledOut_DT":null,"CI_ID":1,"CINotice_DT":"2016-01-07T00:00:00","CIOIMAllegNotes":null,"CIMonitorRolledOut2":null,"CIMonitorRolledOut3":null,"CIMonitorRolledOut4":null,"CIMonitorRolledOut5":null,"CIMonitorRolledOut6":null,"CIMonitorRolledOut7":null}],"COMP_ID":1,"FileNum":"case1","Received_DT":"2016-01-21T00:00:00","Completed_DT":null,"OIMIntake_DT":null,"Status":null,"Occurred_DT":null,"ComplaintType":null,"Source":"Chiefs Office","Precinct":"District 2","AddrCity":null,"AddrState":null,"AddrZip":null,"CaseSummary":null,"IABNotified_DT":null,"ClosureLetSent_DT":null,"CaseType":null,"OIMOutcome":null,"InitialFinding":null,"ClosedFindings":null,"OIMRecFinding":null,"timestamp":null,"Department":"DSD","Address":null,"DeclineReason":null,"Filenum2":null,"Filenum3":null,"OIMDiscRev_DT":null,"OIMInvRev_DT":null,"OIMInvRoute_DT":null,"OIMDiscRoute_DT":null,"CRORoute_DT":null},{"ASSOC_INC_OFF":[],"CRITICALINCIDENTs":[{"CIType":"Officer/Deputy-Involved Shooting","CINotice":null,"CIMonitorRolledOut1":null,"CIDAMonitored":null,"CIOIMQuestions":null,"CICharged":null,"CIMonitor1":null,"CIMonitor2":null,"CINotes":null,"CIOfcCharges":null,"CIOutcome":null,"COMP_ID":2,"RolledOut_DT":null,"CI_ID":2,"CINotice_DT":null,"CIOIMAllegNotes":null,"CIMonitorRolledOut2":null,"CIMonitorRolledOut3":null,"CIMonitorRolledOut4":null,"CIMonitorRolledOut5":null,"CIMonitorRolledOut6":null,"CIMonitorRolledOut7":null}],"COMP_ID":2,"FileNum":"cw1","Received_DT":"2016-01-03T00:00:00","Completed_DT":null,"OIMIntake_DT":null,"Status":"Active","Occurred_DT":null,"ComplaintType":null,"Source":"Citizen Walk-in","Precinct":"District 7","AddrCity":null,"AddrState":null,"AddrZip":null,"CaseSummary":null,"IABNotified_DT":null,"ClosureLetSent_DT":null,"CaseType":"District-Bureau","OIMOutcome":"Satisfactory","InitialFinding":"Formal","ClosedFindings":null,"OIMRecFinding":"Decline","timestamp":null,"Department":"DSD","Address":null,"DeclineReason":"Body Worn Camera","Filenum2":null,"Filenum3":null,"OIMDiscRev_DT":null,"OIMInvRev_DT":null,"OIMInvRoute_DT":null,"OIMDiscRoute_DT":null,"CRORoute_DT":null}]
I am able to bind COMP_ID to my view but when I add in CIType, nothings appears.
console.log($scope.complaints) returns:
My Controller looks like this:
app.controller('UpdateController', function ($scope, ComplaintService) {
getCities();
function getCities() {
ComplaintService.getCities()
.success(function (complaints) {
$scope.complaints = complaints;
})
.error(function (error) {
$scope.status = 'Unable to load customer data: ' + error.message;
});
}
});
My service looks like this:
app.factory('ComplaintService', ['$http', function ($http){
var urlBase = 'http://localhost:63942/api';
var ComplaintService = {};
ComplaintService.getCities = function () {
return $http.get(urlBase+ '/complaints');
};
return ComplaintService;
}]);
and my index looks like this:
<div class="row">
<div class="col-md-3" ng-controller="UpdateController">
<table class="table">
<tr>
<th>Id</th>
<th>CI TYPE</th>
<tr ng-repeat="a in complaints">
<td>{{a.COMP_ID}}</td>
<td>{{a.CIType }}</td>
</table>
</div>
I am certainly confused about why I can render out only COMPID but not the rest of this api contents as it is all listed under localhost:###/api/complaints.
var someResultArray = [];
$scope.complaints.forEach(function(elem){
//basically checks if this exists in the object to avoid undefined issues
if(elem.ASSOC_INF_OFF){
elem.ASSOC_INF_OFF.forEach(function(assoc){
//do something with each assoc, ex: push it to another array
someResultArray.push(assoc);
});
}
});
an object in javascript can be treated by dotting yourself down, or you can also address its content by index, even though its an object. So you could write elem["ASSOC_INF_OFF"], and it would still work.

Resources