0

I'm a noob in AngularJS, therefore sorry for stupid questions.

What I'd like to do is to use the same application in two (or more) places on a page. For that I've created two HTML elements and have bound my app to then using ng-app. The first ng-app would be bootstrapped automatically by angular, the second one has to be bootstrapped manually, which is what I did.

Everything works so far, however when it comes to routing and $location service I've hit a brick wall. Basically if the location is changed using $location service, accessing the route parameter from another instance of the ng-app throws an exception: "[$rootScope:infdig] 10 $digest() iterations reached. Aborting!"

The following is the code I'm trying to get to work:

<table>
    <tr>
        <td>
            <div>
                <div ng-app="mod1App" class="mod1">
                    <ng-view></ng-view>
                </div>
            </div>
        </td>

        <td>
            <div>
                <div ng-app="mod1App" class="mod2">
                    <ng-view></ng-view>
                </div>
            </div>
        </td>
    </tr>
</table>


<script>
    var rootScopes = [];
    var syncStarted = false;
    var mod1App = angular.module("mod1App", ["ngRoute"]);
    mod1App.config(function ($routeProvider) {
        $routeProvider
            .when("/", {
                templateUrl: '/temp/main.html',
                controller: 'MainCtrl'
            })
        .when("/edit/:param1", {
            templateUrl: '/temp/edit.html',
            controller: 'EditCtrl'
        })
    });

    mod1App.controller("MainCtrl", function ($route, $scope, $location) {
        $scope.testClick = function (e) {
            if (e) e.preventDefault();

            $scope.param = $route.current.params.param1;
        }

        $scope.testNavClick = function () {
            syncStarted = false;
            $location.path("/edit/" + Math.random());
        }
    });

    mod1App.controller("EditCtrl", function ($route, $scope, $location) {
        $scope.testClick = function (e) {
            if (e) e.preventDefault();

            $scope.param = $route.current.params.param1;
        }

        $scope.testNavClick = function () {
            syncStarted = false;
            $location.path("/");
        }
    });

    mod1App.run(function ($rootScope) {
        rootScopes.push($rootScope);

        $rootScope.$on("$locationChangeSuccess", function (event, next, current) {

            if (syncStarted == false) {
                syncStarted = true;

                for (var i = 0; i < rootScopes.length; i++) {
                    if (rootScopes[i] !== $rootScope) {
                        //synchronizing scopes
                        rootScopes[i].$apply();
                    }
                }
            }
        });
    });

    angular.bootstrap($(".mod2")[0], ["mod1App", "ngRoute"]);
</script>

Thank you for your help!

2 Answers 2

1

I think the architecture of angular probably prevents this from working the infinite digest error occurs when angular refreshes the view ( in response to a change in the scope) which in turn cause a change in the scope which triggers another digest cycle and so on...

I would therefore question whether what you want to achieve can be done with multiple controllers on the same page rather than multiple apps or if you want different views on the same page with independent navigation then you might look at using the angular-ui ui-router https://github.com/angular-ui/ui-router which allows multiple ng-views on the same page.

Sign up to request clarification or add additional context in comments.

Comments

0

I would guess that you were trying to change the HTML content of your modApp using $routeProvider, which it's likely not going to work.

From my understanding, Angular route provider is used to move the application state forward, and such state is signified through the URL. In this particular use case of yours, how can the URL be represented then, if one of the applications is at main.html, while the other is already at edit.html?

If what you want is actually a single application that has one functionality appearing in two places (instead of two application instances), then I believe using something like a directive should be more suitable for the job.

app.directive('modApp', function() {
    return {
        restrict: 'C',
        templateUrl: '/directive/mod-app.html',
        scope: {
            // if you want separate state handling for each directive instance
            // you define isolated scope for directive here
        },
        controller: function($scope, $rootScope) {
            // define functions related to your directive here
        }
    };
});

Since it's one single app, the application states are shared across the board. Using this approach, you just put ng-app in one place (at html node), but placing directive instances in two places.

<div class="mod-app"></div>

Please note that when defining in JS, you name your directive in camel-case: modApp, while in HTML, you invoke directive with CSS class mod-app.

For more information about directive, you can read it from the official guide: https://docs.angularjs.org/guide/directive

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.