Reputation: 3014
As the title suggests I want to be able to refresh a ng-repeat list from the server every 30 seconds or so. More data can be added on the backend, so I want my list to reflect that. Right now I have the regular $http.get( )
working fine which is here:
$scope.select = function() {
$scope.searchText = '';
$scope.selectedItem = null;
var url = 'http:xxxxxxxxxxxx.com';
url += $scope.selectModel.name;
console.debug("GOING TO: " + url);
$http.get(url).success(function(data2) {
$scope.records = [];
data2.forEach(function(r) {
$scope.records.push(r);
});
});
};
and the portion of the web page it supplies is:
<div style="margin: 1em">
<h4>Search</h4>
<div role="form">
<!-- start dropdown -->
<div class="form-group">
<select class="form-control" ng-options="model as model.name for model in allModels" ng-model="selectModel" ng-change="select()">
<option value="">Choose Model</option>
</select>
</div>
<!-- /end dropdown-->
<div class="form-group">
<input id="start_date" type="text" class="form-control" placeholder="Threat Date">
</div>
</div>
<div>
<table class="table table-hover table-striped" ng-show="records">
<thead>
<th>#</th>
<th>Name</th>
<th>Score</th>
</thead>
<tr data-ng-repeat=" item in records | orderBy : '-score' | limitTo : 10 " ng-click="moreInfo(item)">
<td>{{$index+1}}</td>
<td>{{item.name.slice(5)}}</td>
<td>{{item.score.toFixed(3)}}</td>
</tr>
</table>
</div>
</div>
Is there a way to choose a time @ which the list will refresh? And it has to be without hitting a refresh button or something like that. Thanks in advance.
EDIT This is the error I get when I try and use $interval
as suggested:
ReferenceError: $interval is not defined
at Scope.$scope.select (http:xxxxxxxxxx.com/UserQuery/js/script.js:24:7)
at fn (eval at <anonymous> (https://code.angularjs.org/1.4.0-rc.0/angular.js:12822:15), <anonymous>:2:209)
at Scope.$get.Scope.$eval (https://code.angularjs.org/1.4.0-rc.0/angular.js:15465:28)
at https://code.angularjs.org/1.4.0-rc.0/angular.js:21825:13
at https://code.angularjs.org/1.4.0-rc.0/angular.js:24485:9
at forEach (https://code.angularjs.org/1.4.0-rc.0/angular.js:332:20)
at NgModelController.$$writeModelToScope (https://code.angularjs.org/1.4.0-rc.0/angular.js:24483:5)
at writeToModelIfNeeded (https://code.angularjs.org/1.4.0-rc.0/angular.js:24476:14)
at https://code.angularjs.org/1.4.0-rc.0/angular.js:24470:9
at validationDone (https://code.angularjs.org/1.4.0-rc.0/angular.js:24398:9)
SOLUTION With combined efforts from this and another question, I came to a solution. First off, like many on this question mentioned, the key here is the use of $interval
. There are a few important things to not about using it though.
In my case, where there is a dropdown therefor multiple things I want
to $interval
over, it is important to close one when you open a new
one.
$scope.select = function() { $scope.searchText = ''; $scope.selectedItem = null; $interval.cancel(mainInterval); $scope.url = ''; url = 'http:xxxxxxxxxxxxxx.com'; url += $scope.selectModel.name; console.debug("GOING TO: " + url); $http.get(url).success(function(data2) { $scope.records = []; data2.forEach(function(r) { $scope.records.push(r); }); }); mainInterval = $interval(function() { console.debug("UPDATING...."); console.debug("GETTING NEW FROM " + url); $http.get(url).success(function(data2) { $scope.records = []; data2.forEach(function(r) { $scope.records.push(r); }); }); }, 5000); };
Upvotes: 1
Views: 2933
Reputation: 2599
Try this: Ok, I think the plan is each time select is fired, the existing interval needs to be cancelled and another one started. Have a look at this:
var intervalObj;
$scope.select = function() {
if (intervalObj !== null) {
$interval.cancel(intervalObj);
intervalObj = null;
}
$scope.searchText = '';
$scope.selectedItem = null;
var url = 'http:xxxxxxxxxxxx.com';
url += $scope.selectModel.name;
console.debug("GOING TO: " + url);
$http.get(url).success(function(data2) {
$scope.records = [];
data2.forEach(function(r) {
$scope.records.push(r);
});
});
intervalObj = $interval(function() {
$http.get(url).success(function(data2) {
$scope.records = [];
data2.forEach(function(r) {
$scope.records.push(r);
});
});
}, 30000);
};
I have not been able to fully test this, but the principle is sound.
Upvotes: 0
Reputation: 66971
Just use a $interval()
around your $http
to make it refresh every 30 seconds.
$interval(function () {
$http({
/* run your AJAX and update your $scope / etc */
});
}, 30000); // in milliseconds
Note:
$interval
must be dependency injected into your controller / service / etc to work!
// for examples sake
.controller('MyController', ['$interval', function ($interval) { }]);
Upvotes: 2
Reputation: 2599
Have a look at this:
https://docs.angularjs.org/api/ng/service/$interval
It wraps JavaScript's native setInterval function. You can set it to do the poll every 30 seconds.
It also returns a promise so you can cancel the interval when required.
However, please bear this in mind:
"Intervals created by this service must be explicitly destroyed when you are finished with them. In particular they are not automatically destroyed when a controller's scope or a directive's element are destroyed. You should take this into consideration and make sure to always cancel the interval at the appropriate moment. See the example below for more details on how and when to do this."
EDIT
Taking your code:
$scope.select = function() {
$scope.searchText = '';
$scope.selectedItem = null;
var url = 'http:xxxxxxxxxxxx.com';
url += $scope.selectModel.name;
console.debug("GOING TO: " + url);
$http.get(url).success(function(data2) {
$scope.records = [];
data2.forEach(function(r) {
$scope.records.push(r);
});
});
};
Try changing to this:
$scope.select = function() {
$scope.searchText = '';
$scope.selectedItem = null;
var url = 'http:xxxxxxxxxxxx.com';
url += $scope.selectModel.name;
console.debug("GOING TO: " + url);
$http.get(url).success(function(data2) {
$scope.records = [];
data2.forEach(function(r) {
$scope.records.push(r);
});
});
$interval(function() {
$http.get(url).success(function(data2) {
$scope.records = [];
data2.forEach(function(r) {
$scope.records.push(r);
});
});
}, 30000);
};
If that works you can then refactor the actual $http.get out into a named function to remove the code smell.
Upvotes: 4
Reputation: 3349
Use ng-table instead. Have a look http://bazalt-cms.com/ng-table/
And u can call its reload propery, which will refresh your table,
The reload you can call inside $timeout service provided by angular.
$timeout(function(){
tablename.reload();
},3000);
or
Just call the select function inside the timeout
$timeout(function(){
$scope.select();
},3000);
Upvotes: 0