简体   繁体   中英

AngularJS: Controllers registering multiple times when changing state with UI Router

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

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

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': {},
    }
  })

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM