Can I use one ng-app inside another one in AngularJS

Solution 1:

From the AngularJS document, the answer is no

http://docs.angularjs.org/api/ng/directive/ngApp

AngularJS applications cannot be nested within each other.

And if not nested, then it's OK, someone already asked this question, refer here:AngularJS Multiple ng-app within a page and the AnguarJS document

http://docs.angularjs.org/api/ng/directive/ngApp

Only one AngularJS application can be auto-bootstrapped per HTML document. The first ngApp found in the document will be used to define the root element to auto-bootstrap as an application. To run multiple applications in an HTML document you must manually bootstrap them using angular.bootstrap instead.

Solution 2:

I found one tricky solution for this problem. The idea is that the "host" application have to somehow jump over the root element of nested application. I used directive for this:

    angular.module("ng").directive("ngIsolateApp", function() {
        return {
            "scope" : {},
            "restrict" : "AEC",
            "compile" : function(element, attrs) {
                // removing body
                var html = element.html();
                element.html('');
                return function(scope, element) {
                    // destroy scope
                    scope.$destroy();
                    // async
                    setTimeout(function() {
                        // prepare root element for new app
                        var newRoot = document.createElement("div");
                        newRoot.innerHTML = html;
                        // bootstrap module
                        angular.bootstrap(newRoot, [attrs["ngIsolateApp"]]);
                        // add it to page
                        element.append(newRoot);
                    });
                }
            }
        }
    });

Example simple app:

// module definition
    angular.module("testMod1",[])
        .service("moduleService", function ModuleService() {
            this.counter = 0;
            this.getCounter = function() {
                return this.counter;
            };
            this.incCounter = function() {
                this.counter += 1;
            }
        })
        .controller("ModuleCtrl", function(moduleService) {
                this.getValue = function() {
                    return moduleService.getCounter();
                };
                this.incValue = function() {
                    moduleService.incCounter();
                };
            });

Now in the markup we can use the ng-isolate-app:

<!-- App instance 1 -->
<body ng-app="testMod1">

<div ng-controller="ModuleCtrl as ctrl">
    {{ctrl.getValue()}}
    <button ng-click="ctrl.incValue()">Click</button>
    <!-- App instance 2 -->
    <div ng-isolate-app="testMod1">
        <div ng-controller="ModuleCtrl as ctrl">
            {{ctrl.getValue()}}
            <button ng-click="ctrl.incValue()">Click</button>
            <!-- App instance 3 -->
            <div ng-isolate-app="testMod1">
                <div  ng-controller="ModuleCtrl as ctrl">
                    {{ctrl.getValue()}}
                    <button ng-click="ctrl.incValue()">Click</button>
                </div>
            </div>
        </div>
    </div>
</div>
</body>

Working example on plnkr

This works in simple cases, I do not know how this will work on complex applications.