I am using Angular Meteor and I have a controller that subscribes to a publish-composite publish which returns two cursors. What I am trying to do is to ng-repeat on one cursor and get value from the second cursor based on the value of the first one. Like this:
{{getName(a.id)}}
where a is one object of the first cursor, and in the controller I have $scope.getName(id) function that returns name from the second cursor, like this:
name = second.find({ID: id}).fetch()[0].name
it worked but the problem is the getName function gets hit for unnecessary number of times. Is there a better way to get data from the second cursor based on ng-repeat object of the first cursor? Is nested ng-repeat the way to do? How can I do it?
Thanks.
It seems as if you are focused on the performance of the ng-repeat. Glad you feel this way! From what I remember, the ng-repeat has been a focus of optimization across many 3rd party libraries and discussions.
In your case, my first attempt would be to bind the value inside the ng-repeat only once. You can do this using the :: syntax on the expression.
For example, this would call the expression once.
<ul ng-repeat="a in items">
<li>{{::getName(a.id)}}</li>
</ul>
At the end of your question you mentioned a nested repeat but your question only mentions a single use of it. Am I missing something?
Disclaimer: I've never used Angular Meteor (or even standalone Meteor) so there could very well be a better way do solve your problem.
via: https://docs.angularjs.org/guide/expression
Related
I have a problem where it looks like I'm going to need to use a Two step view.
The problem is basically that it appears I won't be able to use translate in the view in the way that I get the text as I want. I can solve this by using the translate service in my controller and then rendering the text into a view object there.
I'd rather not iterate over the list multiple times. Is there a way I can use an iterator (some way of saying next() in an ng-repeat statement? so that each time ng-repeat gets the next object, I can transform it then?
<md-list-item ng-repeat="artist in nextArtist() track by artist.name">
I have a ngRepeat block that iterates over an array of objects that draws row accordingly.
One of the properties of the object is a string that requires some transformation before displayed.
Performancewise, is it right to run the function everytime Angular runs its loop?
<div ng-repeat="a in arr">{{ strTransform(a.name) }}</div>
Yes, it is OK, performance-wise and everything, unless:
your transformation function itself is way too expensive, in which case you're doomed, or:
you got a humongous amount of elements to process, in which case you're doomed with the rendering time anyway.
--
As a side note, I'd like to add that you might wanna use an Angular filter (link) for these kinds of operations :)
I am trying to implement ng-repeat with ng-style. It works perfectly. However, I do not understand why my method is called more than the number of elements in my ng-repeat!
Do you know why?
To complete my explanation, I created a : JSFiddle
I think that when your html code is compiled, it executes ng-style directive even if there is no data (when items == null). After that your controller changes $scope.items, forcing other calls to $scope.getStyle().
I think if you put a ng-if="items != null" within ng-repeat, your function will be called only 5 times.
Solution looks fine. The reason for multiple calls is angular digest loop. You can read about it here: http://www.benlesh.com/2013/08/angularjs-watch-digest-and-apply-oh-my.html
It works by running the loop and looking if the values changed for the watches. When they stabilize it ends. You can have multiple passes of the event loop in angular app and that is pretty normal. The limit is set afaik for 10 iterations. If bindings do not stabilize then exception is thrown.
Additional reading, highly recommended:
http://teropa.info/blog/2013/11/03/make-your-own-angular-part-1-scopes-and-digest.html
Part Keep Digesting While Dirty is the answer to your question i believe.
So it is by design.
I've spent several hours trying minor variations of this code, and I don't understand why one works and the other doesn't.
Here's the scenario: I'm trying to present a list of registered users (which I'm getting with a simple database query that returns just a few columns), then when one user's name is clicked on, I'll retrieve more information about that user from the database, and present it in a different view. At the moment, I'm doing this with regular <a> elements with an ng-click directive that sets a value called currentid. Elsewhere in my code, I use $watch() to send out a new database query whenever currentid changes. That part seems to be working (I see the console.log() output from my watch callback, and the database query is spitting out the right data)... but sometimes currentid changes, and sometimes it doesn't, and I cannot figure out why.
A jsfiddle where it doesn't work: http://jsfiddle.net/aLcRL/11/
A jsfiddle where it DOES work: http://jsfiddle.net/aLcRL/12/
(Click on the "rmunn" and "admin" links in the table: the "Currrent ID" value below should update. And please pardon the almost total lack of CSS; I'm a coder, not a graphics designer ("Dammit, Jim!"), and it's also very late in my timezone right now so I have no motivation to pretty this up. It's functional, it demonstrates the problem, and I'm going to leave it at that.)
The only difference between these two is that one is binding to currentid, and the other is binding to vars.currentid. Now, I understand why binding to currentid wouldn't work in the case of a parent and a child scope (the child's value would overshadow the parent's value); since I'm coming from a Python background, this makes sense to me (it's similar to how Python's instance namespaces can shadow the namespaces of anything defined on the class). But in this jsfiddle, I'm only using one controller -- aren't all these variables in the same scope?
I've been beating my head against this all day, and the several Stack Overflow answers I've tried to read (like How does data binding work in AngularJS? for example) have just left me even more confused: $apply() and $digest() and scopes, oh my! So if anyone can give me a nice simple beginner's guide to scopes in Angular (or point me to an already-written one that I've missed), I'd be very grateful.
"I've learned Clojure and Haskell, I can learn a simple Javascript framework," I thought. "This'll be easy." Boy, was I wrong. :-)
You are running into an issue where ng-repeat creates a child scope.
<tr ng-repeat="user in data" blarg="{{user.id}}">
<!-- currentid here is part of the ng-repeat child scope
and not your root scope -->
<td>{{user.userName}}</td>
<td>{{user.email}}</td>
</tr>
If you need to access the parent scope you can use $parent.currentid
{{user.userName}}
You need to use $apply() whenever you modify a value outside of the angular world. For example using setTimeout() or a jQuery Plugin. Calling $apply() alerts Angular to reevaluate the scope to see if anything changed and update accordingly.
I'm pretty much new to angular, but I feel like this is kind of crazy.
I've got multiple collections being displayed via ng-repeat in one controller scope. There's an input field for each list to perform a simple query. I was playing around with various filters in my code and I ended up putting a console.log in my filter function. I realized that every time my filter function was called for one list, it was being called for all of the lists in the scope. Furthermore, it was calling the filter function twice each time. So with 3 collections, filtering one of the lists would call the filter function 6 times.
I thought maybe it was just my custom filter, so I tried it out on the default filter function. Same story. Here's my code:
https://dl.dropbox.com/u/905197/angular-filter-test.html
Go to the console and see for yourself :/
What am I doing wrong here? This seems like such a simple thing but it's doing so much work.
This is normal, angularjs uses a 'dirty-check' approach, so it needs to call all the filters to see if any changes exist. After this it detects that you have a change on one variable (the one that you typed) and then it re-executes all filters again to detect if it has other changes.
See the first answer of this question