Angular Infdig Error, but function is running properly - angularjs

I am continuously getting 'Error: $rootScope:infdig
Infinite $digest Loop' on my app, but the actual function that is causing it is still displaying properly in the browser.
Inside my controller, I am creating the following function:
$scope.time = function(id){
return new Date(parseInt(id.substring(0, 8), 16) * 1000);
}
In my HTML, I am trying to show the time that a blog post was created by pulling in the post's mongoDB id, which I convert to the appropriate format in the $scope.time function:
<span am-time-ago="time(post._id)"></span>
From console.logs and testing in the controller, I can see that:
The correct id is being pulled in from Mongo
The $scope.time() function is correctly converting the id into a date string
The date string is showing up the way I want in the browser
So, what is causing the infinite loop and how can I remove it while still showing the data in this same format?
Any help/ideas would be greatly appreciated!

I'm basing this answer on the assumption that you are using angular-moment.
It looks like angular-moment 'am-time-ago' directive is expecting a model value so it will keep invoking your time function resulting in infinite digest cycles.
So rather construct the time when you get your model and pass this value to the 'am-time-ago' directive. Something like this:
$scope.post.$time = $scope.time($scope.post._id);
and your markup would be
<span am-time-ago="post.$time"></span>
See plunker. Open the console to view when the error occurs.

Related

ng-repeat - I'm confused on it works

I'm pretty new to angular js and I have a question about the ng-repeat. I'm following examples at AngularJs : https://docs.angularjs.org/guide/concepts
The section that I'm currently on is 'Adding UI logic: Controllers'. If you look at the index.html, specifically at the code:
<span ng-repeat="c in invoice.currencies">
{{invoice.total(c) | currency:c}}
</span>
When I run in the browser, everything works as expected, but I notice that invoice.total function runs at least 6 times. How do I know? Well in the index.js I added a console.log function within the total function as seen here:
this.total = function total(outCurr){
console.log(outCurr)
console.log(this.convertCurrency(this.qty * this.cost, this.inCurr, outCurr))
return this.convertCurrency(this.qty * this.cost, this.inCurr, outCurr);
};
I would expect the code to run 3 times because the invoice.currencies only has 3 items:
this.currencies = ['USD', 'EUR', 'CNY'];
However, this is what I see in my browser console window:
Any ideas? Thank you in advance?
user2341963 has probably the good answer so i'll quote it first and i'll add some precision.
The digest cycle runs at least twice to check that a value hasn't
changed. First time it runs for each of the values in this.currencies.
It runs again to check that the first digest cycle hasn't changed any
values. It hasn't so it stops after the 2nd cycle
In angular you have what we call a digest cycle. This cycle watch for any change that happened in the application bind to angular. In order to refresh it. This permit to refresh your DOM when you need without refreshing the whole page.
"The bind to angular" means
Every block between {{}}
Every use of scope.$watch or attrs.$observe which are used massively by directives (ng-model/ng-repeat/...).
I don't know what makes this cycle to trigger twice at start this is probably because of some internal mechanics or the filter that you use. Check this link for more info : https://www.ng-book.com/p/The-Digest-Loop-and-apply/

Angular js UI grid is not getting updated with new content

I am calling $http.get to get new content from the server for angular ui grid. On change of date in the datepicker I trigger an ng-change event to make another http call to get new content. The call is successful but the grid is not updated with new content.$scope.grid.core.notifyDataChange() throws error when called inside the http success call back.Please suggest ways to update the grid with new content.
Please find the plnkr code. when I click load button, I want to update grid with new JSON data using http call but it is not updating grid. http://plnkr.co/edit/S2A3scEoO6QIGFbru3Lr?p=preview
The problem with your example is inside $http's success method(lines 256-260).
$http.get(...).success(
function(data){
$scope.roData = data;
});
There you are just putting your data inside a scope property ($scope.roData), but then you're not doing anything with that scope property.
Furthermore you're trying to assign a wrong value to uiGrid.gridOptions.data with the lines:
if($scope.gridOptions.data ==='rData'){
$scope.gridOptions.data = 'roData';
}
But you did 2 mistakes:
Treating variables as string, and this is not going to work. Inside your JS files you need to access your scope with $scope.nameOfVariable not by using their names as strings like 'nameOfVariable'.
You put these lines outside of your success method, so they are executed before you actually get your data.
I managed to edit your plunker and make it work, you can find it here.
What I did was putting your lines together and fix the name error. I did not put there any if since I don't know what logic you wanted to accomplish.
$http.get(...).success(
function(data){
$scope.roData = data;
$scope.gridOptions.data = $scope.roData;
});

Need explanation on a angular direcive load

I just want to understand why in the following jsFiddle 'here is a lo' is printed three times.
http://jsfiddle.net/wg385a1h/5/
$scope.getLog = function () {
console.log('here is a log');
}
Can someone explain me why ? What should I change to have only one log "here is a log" (that's what I would like this fiddle do). Thanks a lot.
Angular uses digest cycles/iterations to determine when state has changed and needs to update the UI. If it finds any change on one of it's cycles, it keeps rerunning cycles until the data stabilizes itself. If it's done 10 cycles and the data is still changing, you'll see a rather know message: "angularjs 10 iterations reached. aborting".
Therefor, The fact that you are seeing the message displayed 3 times is because you have a simple interface. In fact, you can get up to many more such messages in the log, due to the fact that your directive uses {{getLog()}}. Angular keeps evaluating the expression to see if it changed.
To avoid such problems, under normal circumstances, you should store the value returned by the function you want called only once in the $scope object inside the controller and use that variable (not the function call) in the UI.
So in the controller you'd have $scope.log = getLog() [assuming it returns something, and not just writing to the console] and in the directive use the template {{log}}. This way, you'll get the value only once, per controller instance.
Hope I was clear enough.

angularfire - why can't I loop over array returned by $asArray?

I'm using AngularFire 0.8
I called the following function to get an instance of an array.
var test = $firebase(new Firebase(URL)).$asArray();
When I console.log 'test', I get the following (see screenshot).
It looks like test is an array. However, when I do "console.log(test[0])", I get undefined.
Why isn't test an array with two elements like console.log(test) seems to show it should be???
Help!!
Most likely you're calling console.log on the array before the data is loaded.
To access the data in the array, you have to wait until the data is loaded.
To do that in code, you use this construct:
var test = $firebase(new Firebase(URL)).$asArray();
test.$loaded().then(function(array) {
console.log(array[0]);
});
Update
This answer gets more upvotes than I think it's worth. When you're using AngularJS and AngularFire, it is often a bad omen when you use console.log to debug the data that is loaded.
The AngularFire documentation on handling asynchronous operations now has to say on it:
The easiest way to log the data is to print it within the view using Angular's json filter.
{{ data | json }}
AngularFire tells the Angular compiler when it has finished loading the data, so there is no need to worry about when it be available.

$rootScope:infdig error when paginating filtered data

I'm using ng-paginator-plz to paginate some data in my app. I also want to pass this data through some filters before displaying, so I'm doing:
<paginator class="paginator" data="filteredUsers = (users | filter:search)" page-size="20" export-paged-data-to="paginatedUsers"></paginator>
Then to display the data I ng-repeat through paginatedUsers. This works if I remove the filtering, but with the filter in place I get a [$rootScope:infdig] error.
Searching for this error lead me to answers like this: $rootScope:infdig error caused by filter? - which suggest the issue is because the filter is being evaluated multiple times. How can I fix this?
Edit: I've added the following to my controller JS file:
$scope.filter = function(){
$scope.filteredUsers = $filter('search')($scope.users);
};
$scope.$watch('search', function() {
$scope.filter();
});
I also added $filter to the top where depdendencies are passed in. But this gives me a $injector:unpr error when the page first loads and whenever the filter is used. If I change the filter line to $scope.filteredUsers = $scope.users; the error goes (but obviously it doesn't do any filtering), so I guess there's something wrong with my code there.
You can filter it manually in controller in the moments you think it's necessary to refilter data, and store filtered data in separate $scope variable.
With loDash for shortness.
$scope.filter = function(){
$scope.filteredUsers = _.filter(users, function(user){return user.name.indexOf($scope.search) !== -1;});
// or any kind of angular filters..
}
$scope.$watch('search', _.debounce($scope.filter, 100));
<paginator data="filteredUsers" ....></paginator>

Resources