Check if AngularJS module is bootstrapped
Asked Answered
M

2

10

I have an iframe with ASP.NET application, that contains UpdatePanel. I started using Angular inside the application, but things didn't work because of the .NET postbacks.

To solve this, I used this solution:

with (Sys.WebForms.PageRequestManager.getInstance()) {
            add_endRequest(onEndRequest); // regester to the end Request
        }

function onEndRequest(sender, args) {
    angular.bootstrap($('#mainDiv'), ['defaultApp']);
    var rootscope = angular.element('#mainDiv').scope();
    if (rootscope) {
        rootscope.$apply();
    }
}

And it works great.

The problem is that when I dynamically load a different user control in the ASP.NET page, with another ng-controller, Angular throws an error saying the app is already loaded:

App Already Bootstrapped with this Element

So the question is: How can I check if the app is already bootstrapped? Can I reload this module? Can I remove it from the element and than bootstrap it again?

Thanks.

Morphophoneme answered 8/2, 2015 at 9:27 Comment(0)
C
19

It's not good practice to access scope from outside the app, so it's not enabled in well-built production applications. If you need to access/apply scope then there's something strange/unsupported about your use case.

However, the right way to check whether an element has been bootstrapped is the way the Angular library does it which is to load up the element and check for an injector. So you'd want angular.element(document.querySelector('#mainDiv')).injector(); which makes your code:

function onEndRequest(sender, args) {
    var element = angular.element(document.querySelector('#mainDiv'));

    //This will be truthy if initialized and falsey otherwise.
    var isInitialized = element.injector();
    if (!isInitialized) {
        angular.bootstrap(element, ['defaultApp']);
    }

    // Can't get at scope, and you shouldn't be doing so anyway
}

Can you tell us why you need to apply the scope?

Canoness answered 28/12, 2015 at 22:8 Comment(5)
Can you give me some references about how you are using injector? You are calling it on a dom element, where can I find some references about this use? ThanksLemcke
@user449689: There aren't any beside the angular internals. I had to read their code to figure it out. AFAIK, this is the only place where it is published as the right approach.Canoness
element.injector() is undefined even after bootstrapping.Tap
@Tap This answer worked 4 years ago and I haven't used Angular in a few years. I wouldn't be surprised if they changed this behavior in the interim. I'd suggest looking at the angular source code to see what changedCanoness
@Tap Were you able to fix the undefined issue ?Slype
S
4

You could simply check for the scope of mainDiv, if angular.element(document.querySelector('#mainDiv')).scope() is not undefined then that means angular has been not initialized yet.

You code will be like below.

CODE

function onEndRequest(sender, args) {
    //below flag will be undefined if app has not bootsrap by angular.
    var doesAppInitialized = angular.element(document.querySelector('#mainDiv')).scope();
    if (angular.isUndefined(doesAppInitialized)) //if it is not 
        angular.bootstrap($('#mainDiv'), ['defaultApp']);
    var rootscope = angular.element('#mainDiv').scope();
    if (rootscope) {
        rootscope.$apply(); //I don't know why you are applying a scope.this may cause an issue
    }
}

Update

After angular 1.3+ release in later Aug 2015, there it added performance related improvement by disabling debugging information by disabling debug info. So normally we should enable debuginfo option to false to have good performance improvement on Production environment. I don't wanted to write too much about it as its already covered by @AdamMcCormick answer, which is really cool.

Snakebird answered 9/2, 2015 at 18:57 Comment(8)
Won't angular.bootstrap(...) cause Angular to attempt to bootstrap the application each time this function is called?Agnate
Agree, DIMM. angular.element(...).scope() would be better.Leslielesly
@Leslielesly I think that is what I'm doingSnakebird
Best practice is to turn off debug info in production ($compileprovider.debuginfoenabled(false)), so this method won't work if that is the caseCanoness
.scope() should not be used for anything other than debuggingAgentive
@AdamMcCormick when I wrote this answer, in Feb 2015 angular doesn't have $compileprovider.debuginfoenabled(false) option for performance improvement. that has release later in 1.3+ version of angular.. apology that I can't update my old answer list as I have too many answer..I know you had correct point..Though thanks for heads up..Snakebird
@PatrickLawler thanks for heads up.. look the above comment..mine answer was older, before angular 1.3 version wasn't released..please remove downvote..I don;t see any reason behind having.. thanks :-) I can't be predict future as you know everytime technology upgrades by finding bug in older way of doing it..Snakebird
@PankajParkar I appreciate the followupCanoness

© 2022 - 2024 — McMap. All rights reserved.