I am currently on a project that requires me to use angular to call in JSON data from a Rest API.
I am currently only able to pull in one table from MySQL DB. I am required to pull in 3 tables from 1 DB and display data from the tables in one table view on the client side.
3 APIs available via my restful service.
rest/api.php/players
rest/api.php/groups
rest/api.php/teams
The code I have tried and tested will not work, but the below code is a working version of a single DB table.
the HTML:
<div ng-app="myApp" ng-controller="customersCtrl">
<button ng-click="myFunc()">Click Me!</button>
<div ng-show="showMe">
<table>
<tr ng-repeat="x in myData">
<td>{{ x.TeamID }}</td>
<td>{{ x.TeamName }}</td>
<td>{{ x.TeamGoals }}</td>
</tr>
</table>
</div>
</div>
And the angular:
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
$scope.showMe = false;
$scope.myFunc = function() {
$http.get("rest/api.php/teams").then(function (response) {
$scope.myData = response.data.teams;
});
$scope.showMe = !$scope.showMe;
}
});
Related
I want to get the values of the two object in thesame ng-repeat
$http.get('/api/PreviewPayroll').success(function (data){
//alert(data[0].empID);
$scope.allowance = data;
});
$http.get('/api/Deduction').success(function (data){
//alert(data[0].empID);
$scope.Deduction = data;
});
<tr ng-repeat="item in allowance && ng-repeat="value in Deduction">
<td>{{ item.empID }}</td>
<td>{{ value.empID }}</td>
</tr>
how can I get the two scope object on thesame ng-repeat
So you will want to combine the data.
You can use $q.all(promises):
var promise1 = $http.get('/api/PreviewPayroll');
var promise2 = $http.get('/api/Deduction');
$q.all([promise1, promise2]).then(function (results) {
var allowances = results[0];
var deductions = results[1];
var combinedList = /* some combination logic */;
});
By using $q.all() you are ensuring you have both lists of data before trying to combine anything. You can easily play around with this to get the desired effect. For example, if you don't care if the other list isn't available.
Then you can use the ng-repeat in order to iterate over that new combined list:
<tr ng-repeat="item in combinedList">
<td>{{ item.allowance.empID }}</td>
<td>{{ item.deduction.empID }}</td>
</tr>
The sub properties allowance and deduction are based on your combined list.
However
It is in my honest opinion that, the server side gives you the data in the format you need to display it in. (i.e. the business logic remains server side in a controlled environment). I believe the view should only deal with view logic, like button actions etc..
But this is my opinion, and is what I find easiest.
Another note
I prefer to also keep the view logic in the JavaScript, hence why I combine the data there. Rather than trying to do some overly complicated angular expression in the HTML.
You could either have a nested ng-repeat and also combine the two objects into one.
<table>
<tbody ng-repeat="row in mainCombinedObject">
<tr>
<th>{{row.empID}}</th>
</tr>
<tr ng-repeat="sub in row.subObject">
<td>{{sub.empID}}</td>
</tr>
</tbody>
</table>
Combine $scope.allowance and $scope.Deduction to one list of objects "combined" then do your ng-repeat:
<tr ng-repeat="c in combined">
<td>{{ c.someField }}</td>
<td>{{ c.someOtherField }}</td>
</tr>
You can't do that in such way! If your allowance and Deduction have the same size you have to mix them in the collection like this:
var array = [
{ allowance: value1, Deduction: value2},
{ allowance: value3, Deduction: value4},
...
];
and them use it in the view:
<tr ng-repeat="item in array">
<td>{{ item.allowance.empID }}</td>
<td>{{ item.Deduction.empID }}</td>
</tr>
So we're developing this angular app with a firebase backend. I am having trouble with this particular function we're implementing. Basically what it does is every time a different option is selected, the showData() function fires to retrieve the relevant data from firebase (and it works). The problem is that the ng-repeat only updates on the first selection change. Successive selection changes are not reflected in the ng-repeat (although the data is retrieved and thus, the model changed).
View:
<div class="container" ng-controller="dataController">
...
<select ng-model="selectedOption" ng-change="showData()">
<option ng-repeat="entry in transactions" ng-value="entry.serial">{{ entry.serial }}</option>
</select>
</div>
<div class="col-md-9">
<table class="table table-hover table-striped table-condensed">
...
<tbody>
<tr ng-repeat="entry in dataHistory">
<td>{{ entry.id }}</td>
<td>{{ entry.timestamp | date:"yyyy MMM dd 'at' h:mm:ssa" }}</td>
<td>{{ entry.amount }}</td>
</tr>
</tbody>
</table>
</div>
Controller:
...
.controller('dataController', ['$scope', '$firebaseArray', function($scope, $firebaseArray) {
...
$scope.showData = function() {
$scope.dataHistory = [];
transfersRef.orderByChild('serial').equalTo($scope.selectedOption).on('child_added', function(snap) {
transactionsRef.orderByKey().equalTo(snap.val().transactionID).on('child_added', function(data) {
var entry = {};
entry = data.val();
entry.id = data.key();
usersRef.child(entry.fromUserId).child('name').once('value', function(nameSnap) { entry.fromUsername = nameSnap.val(); });
usersRef.child(entry.toUserId).child('name').once('value', function(nameSnap) { entry.toUsername = nameSnap.val(); });
console.log('entry: \n' + entry);
$scope.dataHistory.push(entry);
});
});
};
}])
...
Try applying $scope.$apply() after $scope.dataHistory.push(entry); in your code.
This is because your array updating code maybe outside the angular digest cycle.
I am having a hard time getting the Angular paging to work correctly. The number of pages seems to be off. For example, for one of my searches, the number of returned results is 1005. Displaying 16 results per page, should have 63 pages total. Instead it generates 101. I appreciate any suggestions on why this is happening and how to resolve.
Thanks in advance!
<table class="table table-striped results">
<thead>
<tr>
<th ng-repeat="x in json.headers">{{ x }}</th>
</tr>
<thead>
<tbody>
<tr ng-repeat="x in filteredResults">
<td>{{ x.name }}</td>
<td>{{ x.city }}</td>
<td>{{ x.state }}</td>
<td>{{ x.zip }}</td>
<td>{{ x.phone }}</td>
</tr>
</tbody>
</ul>
</table>
<pagination
style="position:absolute; bottom:10px;"
ng-show="json.results.length"
ng-model="currentPage"
total-items="json.results.length"
max-size="maxSize"
boundary-links="true"
next-text=">"
last-text=">>"
previous-text="<"
first-text="<<">
</pagination>
JavaScript
var app = angular.module('myApp', ['ui.bootstrap']);
app.controller('formCtrl', function($scope, $http){
$(document).ready(function(){
$('.submit-search').click(function(){
$http.get('model/search_url.php', {
params: { searchBy: $scope.user.searchBy, search: $scope.user.search }
}).success(function (response){
$scope.json = response;
$scope.filteredResults = [];
$scope.currentPage = 1
$scope.numPerPage = 16
$scope.maxSize = 5;
$scope.$watch("currentPage + numPerPage", function() {
var begin = (($scope.currentPage - 1) * $scope.numPerPage);
var end = begin + $scope.numPerPage;
$scope.filteredResults = $scope.json.results.slice(begin, end);
});
});
});
});
You're missing the items-per-page, in your case it should be 16, but since you don't provide it it set to the default of 10 items per page.
I have to start polling the server to get the data for multiple table rows, I am having these in ng-repeat.
<table class="table table-bordered" >
<tr>
<th>Id</th>
<th>Title</th>
<th>Amount</th>
<th>...
</tr>
<tr ng-repeat="data in dataList">
<td>
<div>{{ data.id }}</div>
</td>
<td>
<div>{{ data.title }}</div>
</td>
<td>
<div>{{ data.amount }}</div>
</td>
</tr>
</table>
here I have to poll for each row separately ,so that the amount increased or decreased can be viewed . When I amount reaches 100 I have to stop polling for that row.
$scope.pollServer = function(id) {
$scope.pollTimeout = $interval(function() {
$scope.getAmount(id);
}, 1000);
};
can anyone suggest the best way to poll multiple threads in angular . And how to stop for an individual thread.
TL;DR Only update model, ngRepeat is magical.
Do your polling in a service, bind it to $scope in your controller.
app.factory('dataService', ['$http', '$q', function($http, $q){
return {
pollServer: function() {
return $http.get('url'); // do some call to API
}
}
}]);
In controller:
$scope.dataListPromise = dataService.pollServer();
$q.all([dataListPromise]).then(function(results){
$scope.dataList = results[0];
});
Remember to inject $q to controller as well. You can keep your ngRepeat the same as it is now, but it's probably a good idea to track your database results with the id from database. And because you are now dealing with a deferred, you can use ngCloak with ngRepeat to avoid showing pre-rendered $scope variables to user.
I need have raw html which should be inserted to view as is.
<table>
<tr ng-repeat="el in tableRowsHTML track by $index" ng-bind-html="el">
{{el}}
</tr>
</table>
app.controller('Controller', function ($scope, promiseTemplateObj, $sce) {
$scope.tableRowsHTML = [];
$scope.generateTableRows = function(){ ....};
$sce();
$sce.trustAsHtml($scope.tableRowsHTML[1]);
$sce.trustAsHtml($scope.tableRowsHTML[2]);
$sce.trustAsHtml($scope.tableRowsHTML[3]);
How to fix it?
UPDATE:
I get it partially working with ui-router but problem persists.
<tr ng-repeat="el in tableRowsHTML track by $index" ng-bind-html="el | toTrusted"></tr>
Filter (just for example):
appRoot.filter('toTrusted', ['$sce', function ($sce) {
return function (text) {
return text ? $sce.trustAsHtml(text.replace(/\\n/g, '<br/>')) : '';
};
}]);
Where appRoot - your application.
Update: example http://jsfiddle.net/c5j92821/
You can have a look for ng-sanitize as well. This will help you in binding html from controller to the body. And have a look on this page for few of the examples