I'm having some AngularJS trouble with firing off a directive when ng-repeat has completed an update. I have three named arrays, switched to via three links, allowing the selected array to be displayed by the ng-repeat. I'd like to fire some code off when it's finished as I'm planning to set some element attributes for D3 to use.
I've tried checking scope.$last in my directive, but this isn't called at the end of every ng-repeat process. If some of the data remains the same, it may not set scope.$last to true.
http://plnkr.co/edit/hwmOlI6YrgS4H1C1h7k2?p=preview
So, what's the best way to trigger code in a directive when ng-repeat has finished?
Here is a solution for you. Note that the last triggers each time now.
http://plnkr.co/edit/xV1quqzorzxliS2shrP4?p=preview
You just need to $watch the $last variable and it will work fine. This helps in situations where the scope is not created but just updated with new values. Your directive gets created once and if one of the repeated variable just changes values ng-repeat optimizes and just updates values ( as opposed to removing all the values and re-creating the new ones. ). In this scenario, the $scope.$last will be an updated variable and not something that gets "created". So, you will need to $watch it.
Related
Is there an easy way to remove the contents of a div in Angular,
I have <div class="row"> inside of which I have an ng-repeat that generates several widgets. Now if an action takes place from the parent scope I need to empty that div and call the function that does the ng-repeat again.
Without code it's kind of hard to answer this, but if the ng-repeat is only thing in your div, if you update the array/object bound to the ng-repeat it will automatically update the contents of the div because the ng-repeat will re-evaluate. You don't have to clear it out. Now, if you have other content in the div, this solution won't work.
Angular watches the variables on its own and adds / deletes / updates the ng-repeat on it's own when the array it lists gets updated.
So there is no need to delete it all first, you can just update the object / widget you'd like OR replace the contents of the array it lists with a new array.
May be you are updating data outside of AngularJS.
You can try scope.$apply or an easier way is to wrap the function in an $timeout without delay:
$timeout(function(){ // Update your data });
I have a situation where I am generating a LOT of rows and columns using Angular and the performance is terrible!!
I'm assuming that it's because my ng-repeat is creating a new scope for each of the elements that it creates, however, this particular function doesn't need to watch anything. I'm simply using ng-repeat as a loop to generate HTML that will never change.
Is there another angular method that I can use to loop through model data and generate HTML without using ng-repeat that will improve performance?
You can create a directive which will accept the ng-repeat values and then do whatever you want to do in that directive e.g. create a table which will have those values.
You actually need the scope to access the data for the current iterations item.
However, as your data never changes, you might get take a look at bindonce or the slyRepeat directive.
I asked this question on programmers stackexchange a few days ago and didn't receive any replies, so I thought I'd try here.
I have a table that has around 60 rows and 20 columns. Each cell has a directive with an isolated scope. I use 2 nested ng-repeats to generate the table (one for rows and one for columns), but I'm wondering how angular handles scope when a digest cycle causes a re-generation of the directives in the ng-repeats?
Does it destroy all the previous isolated scopes in my directives and create new ones, or are those old isolated scopes now orphaned somewhere and memory leaking as more and more digests take place?
Is this something that I, as a developer, should be aware of and make sure to handle the destruction of any isolated scopes?
The ng-repeat creates a $$hashKey attribute in your $scope for all the values you are displaying. Whenever the $digest is called, it checks if the values changed or not. ng-repeat is usually one of the culprits in slow angular applications for multiple reasons.
You may not need to watch the variables. If you just want to show some data which doesn't get updated often you might as well remove the double-binding so angular doesn't have to create entries for them in the $scope
Never use a function result as a ng-repeat value because the function will run on every $digest cycle
Don't use filters since they get called twice in the $digest cycle and slow down the ng-repeat
Here's some more information about ng-repeat and angular performance.
Is there a built-in method to AngularJS to remove the automatically created watch on a value inserted into a template via curly braces.
For example:
<span>{{someVal}}</span>
In my case, someVal is never going to be changed after it's loaded the first time. I don't need the watch code listening for changes. I'm trying to speed up a page's performance that has a rather large table - some values the user can edit but most are read-only values.
I'm not setting up a watch manually so I don't have a reference to the deregistration method for each value. Do I need to write a custom directive to achieve this?
A buddy of mine found this set of directives for this exact purpose.
https://github.com/abourget/abourget-angular
I have recently found a better way of doing it as it's built in the angular:
<span>{{::someVal}}</span>
More information here: https://docs.angularjs.org/guide/expression
I'm trying to change an input box value referring to its model.
The input box is inside an ng-repeat, that gets its elements from a function and not from a variable.
Is there a way for the application to print the model full path/name so that I can refer to it from the controller? (Note that the models are working, since a division beneath it with ng-show responds properly to the input model being filled.)
In general, you shouldn't use a function inside an ngRepeat. With the way the digest cycle works, your function will end up getting called multiple times. That's not very efficient. Instead, you should run the function from your controller and assign it to a scope variable that you pass to ngRepeat.
As it turns out, this makes the solution to your problem quite easy. You could for example use each item's $index to reference it from the controller.
If you post a fiddle or plunker, I can update this answer with something more specific. But it's hard to say more without some code.