angular.bootstrap error: Error: [ng:btstrpd] App Already Bootstrapped with this Element
Asked Answered
B

1

3

I'm building a widget that depends on Angular along with a widget builder tool. The builder used Angular with ngApp attached to the html tag of the document.

When I load up the widget within the widget builder, I get the following error:

Error: [ng:btstrpd] App Already Bootstrapped with this Element '<div class="company-widget" id="widget-app" data-company="demoCorp">'

Here is the bootstrap function:

angular.bootstrap('#widget-app', ["myWidget"]);

For all intents and purposes, the rest of the myWidget app is a pretty standard mix of controllers and services.

I was following along with this blog post on how to allow multiple ngApp directives in a single page, however I didn't realize until after I set this thing up that it says right at the end of the blog post that you can't nest apps, which is what's happening here, and what may occur on a small number of sites that use this widget.

I can't redesign the widget-builder and I can reasonably assume that for any Angular sites where the widget is embedded, the host site will attach ngApp to the html tag.

My question is, is there a way to get around this limitation, even if it's a hacky solution? Is it possible to check if the page already has an app and inject the myWidget app into the host app as a dependency?

Brolly answered 11/1, 2016 at 20:52 Comment(2)
The fact that Angular is reporting that the element already bootstrapped means that there must be some way to tell - though that code might be internal to AngularJS. To find out you could reference the unminified version of AngularJS and breakpoint on that error to see the if condition. From what I can make out of what you are describing, it sounds like you want to dynamically "inject" a module at runtime. If so you might want to take a look at this article: weblogs.asp.net/dwahlin/…Fuller
No simple way to do this. Can you post the boostrapping code for the widget builder? Do you have access to the same script block that the boostrapping happens in? You said you can't redesign the widget builder, but are there any modules you can piggy back on?Nuno
N
0

You could try something like this:

https://jsfiddle.net/pavy/vnnuxgwo/

// Parent/host application
var myApp = angular.module('myApp', []);

myApp.controller('AppCtrl',
    function($scope) {
        $scope.name = 'YourName';
    }
);

// Third party module
// This needs to happen after myApp is defined
var myWidget = angular.module('myApp');
myWidget.controller('MyWidgetCtrl',
    function($scope) {
        $scope.widgetName = 'This is my widget.';
    }
);

The third party module code (your widget) needs to come after the host app (in your case, this would be the Widget Builder) code.

You're also dependent on the module name of the host app, so if it changes, your code will break. There are likely ways to programmatically get the loaded Angular app name, which would help in this regard.

Nuno answered 11/1, 2016 at 22:25 Comment(2)
I'm not sure I understand how the widget injects itself into the host page's app as a dependency from your example, which I think is the only way to solve this. Anyway, I've put a lot more thought into it and I think an iframe may be the only route her after all, unfortunately.Brolly
Without seeing more code I can't say for sure. But, if you can get the host app via angular.module('myApp') during the bootstrapping, then you can tie your "widget" into the host app. I updated the fiddle, perhaps it'll be more clear now. As long as the host app is not using angular.bootstrap which it shouldn't be, since you said it's using the ng-app directive, then you should be able to tie in with the host app as a normal module, and not need to do any bootstrapping on your end.Nuno

© 2022 - 2024 — McMap. All rights reserved.