1

I am injecting HTML with a ui-view into the DOM, then changing state using ui.router. Everytime the state is changed, that controller seems to be registered an additional time, thus the code in the controller executes multiple times. You can see a demonstration of this with the plnkr below. (just pop open the console, then click back and forth between the left and right button and notice that the controllers execute an additional time for each click.)

If the ui-views live on the index.html as static content then life is good, and the issue does not happen. It is only when injecting them into the DOM.

var app = angular.module('app', ["ui.router", "appHome", "appOther"]).config([
             "$urlRouterProvider", "$stateProvider", "$locationProvider", 
    function ($urlRouterProvider,   $stateProvider,   $locationProvider) {

        $stateProvider.state('appHome', {
            url: '/home/index',
            views: {
                "Alerts": {
                    template: 'THINGS',
                    controller: "AlertsController as Alerts",
                }
            }
        }).state('appOther', {
            url: '/other/index',
            views: {
                "Other": {
                    template: 'THINGS',
                    controller: "OtherController as Other",
                }
            }
        });

    }
]);

Testcase on Plunker: http://plnkr.co/edit/M2wzVLSSgZ7naOi58qgL

2 Answers 2

1

You are amost there. And I am not challenging or judging this approach, just providing the answer. There is a working example .

You've properly created new scope. Very good. But that is just an A. The essential and curcial B is missing. B - is opposite to A === destroy new scope (once old).

This will do the job for us:

 app.controller('MenuController', ["$scope","$compile", "$state","$http",
    function MenuController($scope,$compile, $state, $http) {
        $scope.goToUrl = function (view) {

                // was scope previously created
                var hasPreviousChildScope = this.childScope !== void 0
                                         && this.childScope !== null;

                if(hasPreviousChildScope)
                {
                  // we must clear after ourselves
                  this.childScope.$destroy();
                  this.childScope = null;
                }

                // create new scope
                this.childScope = $scope.$new();

                var html;
                var state;
                if(view == 'Alerts'){
                  view = '<div ui-view="Alerts"></div>';
                  state  = 'appHome'
                }
                else{
                  view = '<div ui-view="Other"></div>';
                  state  = 'appOther'
                }
                $('#test').html($compile(view)(this.childScope));
                $state.go(state);

        };
    }
]);

Check that all in action here

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

Comments

0

Why do you make it so complicated? Is there a special reason why you are using

if(view == 'Alerts'){
   view = '<div ui-view="Alerts"></div>';
   state  = 'appHome'
}
else{
   view = '<div ui-view="Other"></div>';
   state  = 'appOther'
   }

$('#test').html($compile(view)(scope));
$state.go(state);

Isn't it possible to use something like

<div ng-controller="MenuController">
   <button ui-sref="appHome" value="CLick Me">GoTo Alerts</button>
   <button ui-sref="appOther" value="CLick Me">GoTo Other</button>
</div>
<section ui-view></section>

I used ui-sref to easily navigate between states. I have prepared a little demo to illustrate that. Have a look here. Does that help? Is it usable? That way you don't even need the menuController.

If you need named views (multiple nested views) have a look at the documentation. Is is explained pretty well. You would end up with something like:

<!-- index.html -->
<body>
  <div ui-view="alerts"></div>
  <div ui-view="other"></div>
</body>

$stateProvider
  .state('report', {
    views: {
      'alerts': { ... templates and/or controllers ... },
      'other': {},
    }
  })

1 Comment

The reason its like this is because the HTML im injecting (which contains the ui-view) is served up by MVC, where some Razor code hides/show some things based on user security. So basically, the HTML you see me compile is retrieved from a GET to an MVC controller that returns a partial view.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.