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

Commit

Permalink
fix(re-bootstrap): Throw an error when bootstrapping a bootstrapped e…
Browse files Browse the repository at this point in the history
…lement.

Nothing would prevent a user from accidentally calling angular.bootstrap on an element that had already been bootstrapped. If this was done, odd behavior could manifest in an application, causing different scopes to update the same DOM, and causing debugger confusion.

This fix adds a check inside of angular.bootstrap to check if the passed-in element already has an injector, and if so, will throw an error.
  • Loading branch information
jeffbcross committed Aug 9, 2013
1 parent 94ec84e commit 3ee744c
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 0 deletions.
29 changes: 29 additions & 0 deletions docs/content/error/ng/btstrpd.ngdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
@ngdoc error
@name ng:btstrpd
@fullName App Already Bootstrapped with this Element
@description

Occurs when calling angular.bootstrap on an element that has already been bootstrapped.

This usually happens when you accidentally use both `ng-app` and `angular.bootstrap` to bootstrap an application.

```
<html>
...
<body ng-app="myApp">
<script>
angular.bootstrap(document.body, ['myApp']);
</script>
</body>
</html>
```

Note that for bootrapping purposes, the `<html>` element is the same as `document`, so the following will also throw an error.
```
<html>
...
<script>
angular.bootstrap(document, ['myApp']);
</script>
</html>
```
6 changes: 6 additions & 0 deletions src/Angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,12 @@ function angularInit(element, bootstrap) {
function bootstrap(element, modules) {
var doBootstrap = function() {
element = jqLite(element);

if (element.injector()) {
var tag = (element[0] === document) ? 'document' : startingTag(element);
throw ngMinErr('btstrpd', "App Already Bootstrapped with this Element '{0}'", tag);
}

modules = modules || [];
modules.unshift(['$provide', function($provide) {
$provide.value('$rootElement', element);
Expand Down
26 changes: 26 additions & 0 deletions test/AngularSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,32 @@ describe('angular', function() {
/\[\$injector:modulerr] Failed to instantiate module doesntexist due to:\n.*\[\$injector:nomod] Module 'doesntexist' is not available! You either misspelled the module name or forgot to load it\./
);
});


it('should complain if an element has already been bootstrapped', function () {
var element = jqLite('<div>bootstrap me!</div>');
angular.bootstrap(element);

expect(function () {
angular.bootstrap(element);
}).toThrowMatching(
/\[ng:btstrpd\] App Already Bootstrapped with this Element '<div class="?ng\-scope"?( ng\-[0-9]+="?[0-9]+"?)?>'/i
);

dealoc(element);
});


it('should complain if manually bootstrapping a document whose <html> element has already been bootstrapped', function () {
angular.bootstrap(document.getElementsByTagName('html')[0]);
expect(function () {
angular.bootstrap(document);
}).toThrowMatching(
/\[ng:btstrpd\] App Already Bootstrapped with this Element 'document'/i
);

dealoc(document);
})
});


Expand Down

1 comment on commit 3ee744c

@petebacondarwin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The demo on this documentation page is broken because of this commit: http://docs.angularjs.org/guide/dev_guide.services.$location
It is trying to bootstrap two sub-elements of the overall application but is now failing because we are deeming those elements to be bootstrapped already - even though they are wrapped in an element which has ng-nonbindable on it

Please sign in to comment.