How to get root element for scope in angular? - angularjs

I usually need the element's scope which is something like $(element).scope() or angular.element(..).scope()
But now I have the opposite problem - I have a scope, and I need to find which element generated it.
How can I find out from the developers' console which element it is?
Why do I need this?
I am working on someone else's code, fixing a bug.
I am still trying to figure out some stuff, but some of the code is quite hard to follow. Very generic and a lot of copy-paste, so searches don't always help.
There's a lot of ng-includes and directives that use the parent scope.
There's a view calling a service somehow - it is unclear how yet..
I do have a reference to a scope, which is different from the one in the view that triggers the function.
So if I find the element from which that scope came from, it could sort out the relation between them etc.. At least give me some lead.
Obviously some refactoring and best practices are required in the future, but I have to focus on this bug first.

I know of nothing 'out-of-the-box', but every $scope variable has a unique $id property; and in addition, every element that has a $scope gets marked with the 'ng-scope' class. So something along the lines of the following VERY UGLY METHOD! may help (I'm assuming you have jQuery; otherwise substitute angular's jqueryLite methods):
function findById(id) {
var els = $('.ng-scope');
for (var i=0; i<els.length; i++) {
if ($(els[i]).scope().$id===id) {
return els[i];
}
}
return null;
}
And if this is actually helpful, then I feel your debugging pain.

Related

AngularJS getting value from function in ng-if and using that value in element

My question lies in the following code. Though the code is not working now. I wan't to rewrite it in proper way so that it works.
<span ng-if="community = vm.getCommunity(invite.community_id)!=null" grv-icon-comm-type="vm.communityViewHelper.getTypeIcon(community)" ng-class="vm.communityViewHelper.getColorClass(community)"></span>
In the above code vm.getCommunity(invite.community_id) returns either null or community object. If community object is returned then I wish to call two more function in the same element where I wish to use the recently receivedcommunity value on those two function.
It's just killing my time. Please help.
Alternatively, you could use a watcher on "invite.community_id" to set community inside a controller function. Could look a bit cleaner depending on the rest of the code.
This function could even set all three values if you like.

$watcher count exploding in ng-repeat virtual scolling

I am trying to implement a virtual scrolling tree directive in Angular using this guide as a reference. However, when I start scrolling, the $watcher count explodes to 17k-20k+ watchers (which crashes the page), scrolling is consistently slow, and nothing I have tried seems to help.
Plunker with my current code: HERE
(Note, above not showing up for me in Firefox, but is working in Chrome). If you have any thoughts of what else I can try so the scrolling is not a disaster, I am open for ideas. Been working on this for way too long...
Other methods I have tried:
$compile(element.components())(scope.$new())
Was called in onScroll(). Result: The list no longer displayed at all/still lagged badly and I got continual "Cannot call method 'insertBefore' of null on $compile" errors until the page crashed.
<li ng-repeat="node in nodeList" vs-node="node"></li>
Aka, I tried to give each element an isolated scope of its own in hopes that its scope and any watchers associated with it would be destroyed when the list was updated. Result was no difference with the watcher issue of above.
function clearVisibleProvider(nodeList){
for(var i=nodeList.length-1; i >= 0; i--){
nodeList[i] = null;
}
return nodeList;
function clearNode(node){
if(node.nodes){
for(var j=node.nodes.length-1; j >= 0; j--){
clearNode(node.nodes[j]);
}
}
nodeList[i] = null;
}
}
An attempt to clear old list elements before replacing them. Again, no difference. It was called within updateDisplayList() before the main list was updated.
Achieved my goal by redesigning to use a regular list view instead. Displayed nodes are flattened into a list, manual indexing is used to keep track of things, and there is no nesting. Any elements that would be nested have padding calculated based on their level of depth in the tree.
There was also a bug where I was getting too many nodes at once as well. Instead of 50, I'd get 200-500. Fixing that did not solve the watch count exploding however, so I don't consider it the source of the original problem.

Add scope variable to array and then stop data bind

For reference, here is the fiddle: http://jsfiddle.net/6u3Gn/1/
I am playing around with angular and ran into a behavior that I can understand, but am not sure how to stop. I created a simple form for places and things, where you define a place, and then you can add things at that place. When the button to add a thing is clicked, it successfully adds the thing to the place:
$scope.addThing = function() {
if ('things' in $scope.place) {
$scope.place.things.push($scope.thing);
} else {
var things = [$scope.thing]
$scope.place['things'] = thing;
}
};
However, when I try to add another thing, the first one is still bound to $scope.thing, so the first one updates to be the exact same as the second thing I add.
How can I stop the 2 way data binding once the object in the array has been added? Is there a way to do so, or am I going about adding it to the array all wrong?
Well that was easy. Not exactly sure how I missed it but the right way to do this is to use angular.copy($scope.variable). Whoops!

What is the reason for assigning this to a locale variable without a callback?

As far as I know assigning this to a variable is used within callbacks where the this scope may change. But digging through the ExtJS source I found it used in all sorts of functions but not always. So is there any reason that I would assign this to a local variable beneath the scope or is the ExtJS source just struggling with different developer styles?
#kevhender pointed me to the right sencha forum thread where evan has given a very good explanation.
It's only for the size. And here's a example:
function doA() {
var me = this;
me.a();
me.b();
me.c();
me.d();
me.e();
me.f();
me.g();
me.h();
me.i();
me.j();
me.k();
me.l();
}
function doB() {
this.a();
this.b();
this.c();
this.d();
this.e();
this.f();
this.g();
this.h();
this.i();
this.j();
this.k();
this.l();
}
Compressed we get:
function doA(){var a=this;a.a();a.b();a.c();a.d();a.e();a.f();a.g();a.h();a.i();a.j();a.k();a.l()}
function doB(){this.a();this.b();this.c();this.d();this.e();this.f();this.g();this.h();this.i();this.j();this.k();this.l()};
It adds up.
According to that we should
NOT use a local var if we use this only up to three times
function doA(){var a=this;a.a();a.b();a.c();};
function doB(){this.a();this.b();this.c();};
and use it if we use this more often then three times
function doA(){var a=this;a.a();a.b();a.c();a.d()};
function doB(){this.a();this.b();this.c();this.d()};
There are a few reasons for this, the most significant being that using a local variable will save a few bytes during compression of the files. It may not seem like much for a small bit of code, but it can add up a good bit over time.
There is a long thread at the Sencha forums talking about this very issue: http://www.sencha.com/forum/showthread.php?132045.
As you've correctly stated this is sometimes used in places where the scope might change.
There are cases where you want to do the same to make sure there are no scoping issues.
Other than that, the devs sometimes just assign this to a variable out of habit more than out of necessity.

Passing an array from one view controller to the another view controller

I have read all of the posts about passing data from one view controller to another but I am still at a loss as to how that is done. Simply put, I have an array that is built in my MainViewController and need to use that array in my DisplayViewController.
I am simply doing the following
//DisplayViewController
self.items = mainViewController.items
I would think that this notation would work but I keep getting the following error:
Request for member 'mainViewController' in something not a structure or union.
Since I am a real newbie I cannot really understand some of the answers that I read. So if someone can put it in laymans terms, I would really appreciate it!!!
Usually it's done the other way around. Just before you push your DisplayViewController on the stack (or however you make it visible), you set its items property.
detailViewController.items = self.items;
[self.navigationController pushViewController:detailViewController animated:YES];

Resources