Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

angular.element.scope() returns undefined #9515

Closed
marosivanco opened this issue Oct 9, 2014 · 29 comments
Closed

angular.element.scope() returns undefined #9515

marosivanco opened this issue Oct 9, 2014 · 29 comments

Comments

@marosivanco
Copy link

angular.element.scope() is undefined when the application is loaded in iframe by changing the iframe src attribute.

The following code should return reference to scope but returns undefined:

angular.element(document.body).scope()

The code above is executed in the onclick handler after the document is loaded and angular has finished bootstrap:

<script>
    document.addEventListener("click", function(){
        console.log(angular.element(document.body).scope());
    });
</script>

The issue manifests itself only when the document is loaded in the iframe by modifying its src attribute.
Tested with 1.3.0-rc.5, without jquery.

@jeffbcross
Copy link
Contributor

Can you provide a plnkr reproduction of the issue please?

@Toilal
Copy link
Contributor

Toilal commented Nov 4, 2014

I have the same issue in my own project, but can't reproduce it using plnkr.

scope() returns undefined on any element.

Using JQLite or JQuery 2.1.1 does the same.

AngularJS 1.3.1.

@VictorQueiroz
Copy link
Contributor

Try this:

document.addEventListener('DOMContentLoaded', function () {
  angular.element(document.body).scope();
});

@caitp
Copy link
Contributor

caitp commented Nov 4, 2014

are you disabling debug info in your project @VictorQueiroz?

@Toilal
Copy link
Contributor

Toilal commented Nov 4, 2014

@caitp You've found it.

Enabling debug info back is a good workaround for this issue.

@gkalpak
Copy link
Member

gkalpak commented Nov 4, 2014

a good workaround

😄 😄 😄

Toilal added a commit to angular-gantt/angular-gantt that referenced this issue Nov 4, 2014
This adds the first plugin: sortable.

Note that degubInfoEnabled(false) is commented because of issue angular/angular.js#9515
@marosivanco
Copy link
Author

Sorry guys for not reacting for a while. The issue is somehow related to jqCache, or more specifically to the way how expandoId is created. In older RCs, the id was created like this:
var expandoId = element[JQLite.expando];
In newer ones, the id is get using hardcoded property:
var expandoId = element.ng339;
Reverting the change solved the issue.
Unfortunately, I do not know much about the stuff, so if somebody could shed light on the functionality, then perhaps I would be able to describe the issue in more detail.

@ocombe
Copy link
Contributor

ocombe commented Nov 6, 2014

Oh wow thanks @caitp that was driving me mad !
There should be a note in the doc on the $compileProvider explaining that $compileProvider.debugInfoEnabled(false) will make the scope() function return undefined, if that is the expected behavior.

Edit: my bad, it's already in the doc

Call this method to enable/disable various debug runtime information in the compiler such as adding binding information and a reference to the current scope on to DOM elements.

@ronnievdv
Copy link

Is there a way around this; having debugInfoEnabled(false), but still being able to access the scope of an element?

@gkalpak
Copy link
Member

gkalpak commented Nov 19, 2014

If you want to enable debug information temporarily (e.g. for debugging an issue on a live production app) you can use angular.reloadWithDebugInfo() as described here.

@pkozlowski-opensource
Copy link
Member

I think that @gkalpak clarified things here!

@Toilal
Copy link
Contributor

Toilal commented Nov 19, 2014

Why closing ? Finding a workaround doen't means the issue is fixed, scope() should return the attached scope regardless the debug mode.

If not possible, it should be be cleary documented in angular.element#scope() doc.

@pkozlowski-opensource
Copy link
Member

@Toilal I've closed it since it is documented already as mentioned in the previous comments of this thread. But if you believe that it should documented in other places as well a PR would be much appreciated!

@Toilal
Copy link
Contributor

Toilal commented Nov 19, 2014

I can't because i'm not sure witch methods from angular.element won't work when disabling debug. scope() for sure because i've tried it, but how about the others, like controller(), injector() ...

@Toilal
Copy link
Contributor

Toilal commented Nov 19, 2014

After testing, it only impacts scope() and isolateScope(). I'll document those and make a PR.

But is there any way to retrieve the scope from a DOM element while having debug info disabled ?

@pkozlowski-opensource
Copy link
Member

@Toilal - not really - scope info was removed as exposing it has perf impact - this is why it is hidden behind a debug flag.

Toilal added a commit to Toilal/angular.js that referenced this issue Nov 19, 2014
@ocombe
Copy link
Contributor

ocombe commented Nov 19, 2014

But it wouldn't be that hard to write a directive that could do that and put it on the elements that you need to check

@Toilal
Copy link
Contributor

Toilal commented Nov 19, 2014

Thanks @pkozlowski-opensource. I've added a small sentence on scope() and isolateScope() in docs, because it takes me some times to figure out why those methods didn't work in my application.

@Toilal
Copy link
Contributor

Toilal commented Nov 19, 2014

@ocombe That's what i'll do, because i'm writing a UI component and can't rely on scope/isolateScope as end developer could disable debug info (as it's recommended).

VWoeltjen added a commit to nasa/openmct that referenced this issue Oct 28, 2015
element.scope() may be undefined when wiring in the info
gesture, so check for that.

That this is sometimes undefined appears to be a consequence
of changes to mct-representation, but which changes influence
this are unclear. In any event, it appears that this cannot
be relied-upon per angular/angular.js#9515
@shijiaoliang
Copy link

setTimeout(function() {
console.log(angular.element(document.body).scope());
}, 100);

qq 20160115164505

@ghost
Copy link

ghost commented May 26, 2016

@ronnievdv

Is there a way around this; having debugInfoEnabled(false), but still being able to access the scope of an element?

I've used the following snipet (not recommended) method in the link function of the directive definition.

link: function(scope, element, attrs) {
  var isolatedScope = scope.$$childTail;
}

@hemkaran
Copy link

Is there any way to check if debugInfo has been disabled or any flag for it?

@gkalpak
Copy link
Member

gkalpak commented Jun 28, 2016

From within the app, you can use $compileProvider.debugInfoEnabled().
If you want to debug a live instance that has debug info disabled (e.g. a production deployment), you can call angular.reloadWithDebugInfo() from the console and it will reload the app with debug info enabled.

@hemkaran
Copy link

hemkaran commented Jun 29, 2016

@gkalpak I just want to check if debug info is enabled or not. Somewhat like this.

if(angular.isDebugInfoEnabled()) {
  // Do something
}

@gkalpak
Copy link
Member

gkalpak commented Jun 29, 2016

@hemkaran , it is still not obvious where you want to check it from. I assume from inside your app.
If that is indeed the case, you can use $compileProvider.debugInfoEnabled().

@adrianschmidt
Copy link

@Toilal Did you write a directive like that? If so, would you mind sharing? I'm having this problem right now. I assume I'll find a solution, but having a second opinion on how to solve it really wouldn't hurt.
cc @ocombe

@ocombe
Copy link
Contributor

ocombe commented Dec 15, 2016

Sorry I don't use Angular 1 anymore, and I never had to write such a directive (because I only needed this info in dev mode)

@adrianschmidt
Copy link

I did the following. We'll see if my teammates will let it through the review :)

function exposeScope() {
    return {
        restrict: 'A',
        link: function(scope, element) {
            element[0].APPNAME = {
                getScope: function() {
                    return scope;
                }
            };
        }
    };
}

@carmen-mvp
Copy link

return {
        restrict: 'A',
        scope: false,
        link: function(scope, elem) {
            elem.data('$scope', scope);
        }
    };

You can also set $isolateScope to the same if you need it.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.