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.
Related
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;
}
});
UPDATE: It was because not setting the values for $scope.quantity
I have 3 places where I should ng-repeat 3 different data sources.
I use 3 controllers, from which only the 1st one displays data. The other two can console.log the data, but do not display it.
I really can't understand why everything works for the 1st set of data, but not for the rest, even though the code is pretty much the same for all of them.
js
//this is working
function publisherController($scope, $http) {
//$scope.sortType = 'name'; // set the default sort type
//$scope.sortReverse = false; // set the default sort order
$scope.searchPublisher = ''; // set the default search/filter term
$http.get("/ServiceProxy.aspx?apiPath=api/path1")
.then(function (response) {
$scope.pubNames = response.data;
console.log(JSON.stringify($scope.pubNames));
});
$scope.quantity = 5;
};
// this is not working
var formatController = function ($scope, $http) {
//$scope.sortType = 'name'; // set the default sort type
//$scope.sortReverse = false; // set the default sort order
$scope.searchFormat = ''; // set the default search/filter term
$http.get("/ServiceProxy.aspx?apiPath=api/demand/path2")
.then(function (response) {
$scope.formatNames = response.data;
console.log($scope.formatNames);
});
};
//this is not working
function distributorController($scope, $http) {
//$scope.sortType = 'name'; // set the default sort type
//$scope.sortReverse = false; // set the default sort order
$scope.searchDistributor = ''; // set the default search/filter term
$http.get("/ServiceProxy.aspx?apiPath=api/path3")
.then(function (response) {
$scope.distributorNames = response.data;
console.log(JSON.stringify($scope.distributorNames));
});
};
html
<div class="row" ng-app>
<-- This is working -->
<div ng-controller="publisherController">
<table class="table table-bordered table-striped">
<tbody id="format">
<tr ng-repeat="roll in pubNames | orderBy:sortType:sortReverse | filter:searchPublisher | limitTo:quantity">
<td><input type="checkbox" id="myCheck">{{roll}}</td>
</tr>
</tbody>
</table>
</div>
<-- This is NOT working -->
<div ng-controller="formatController">
<table class="table table-bordered table-striped">
<tbody id="format">
<tr ng-repeat="f in formatNames | orderBy:sortType:sortReverse | filter:searchDistributor | limitTo:quantity">
<td><input type="checkbox" id="myCheck">{{f}}</td>
</tr>
</tbody>
</table>
</div>
<-- This is NOT working -->
<div ng-controller="distributorController">
<table class="table table-bordered table-striped">
<tbody id="distributor">
<tr ng-repeat="d in distributorNames | orderBy:sortType:sortReverse | filter:searchDistributor | limitTo:quantity">
<td><input type="checkbox" id="myCheck">{{d}}</td>
</tr>
</tbody>
</table>
</div>
</div>
Data is retrieved in my AngularJS app via $http.get and rendered like this:
# Angular
app.controller('MainCtrl', function ($scope, $http) {
$scope.cart = {};
$scope.cart.retrieve = function() {
// make $http to retrieve data
.success(function(results) {
$scope.cart.contents = results
});
};
$scope.cart.update = function(itemId) {
// make $http request to update cart
}
});
# HTML
<table ng-init="cart.retrieve()">
<tbody>
<tr ng-repeat="item in cart.contents">
<td>{{ item.price }}</td>
// item quantity input field
<td><input type="number" name="quantity" on-change="cart.update(item.id)"
ng-model="item.qty"></td>
<td>{{ item.price * item.qty }}</td>
</tr>
</tbody>
</table>
When the item quantity is changed in input field, the function that passes item id fires: $scope.cart.update = function(itemId) { ... } . How do I retrieve this new quanity value for this particular item that triggered on-change event. Is there something in angular like this I can use inside the function?
You can pass item to your cart.update function:
on-change="cart.update(item)"
And then use the qty of this item
$scope.cart.update = function(item) {
// do whatever you want with
// item.qty
}
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.