Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically add existing controller into another controller with AngularJS

Tags:

angularjs

in my app I have a wrapper controller that handles some properties dynamically based on other-controllers within it. everything works like a charm if the other-controllers are present/static on load, but as soon as I'm trying to make them dynamic, they stop working.

It was my understanding that the $rootScope is available from everywhere within the app, is that not true?

my JS looks like this:

  var webApp = angular.module("webApp",[]);

  webApp.controller("ControllerA", function($scope, $rootScope){
    $rootScope.cnt = 0;
    $rootScope.cntPlusPlus = function(){
      $rootScope.cnt++;
    };

    $rootScope.controllerBs = [];
    var template = $(".controller-b").html();
    $scope.addControllerB = function(){
      $rootScope.controllerBs.push(template);
    };
  });

  webApp.controller("ControllerB", function($scope, $rootScope){
    $scope.cntPlusPlus = function(){
      console.log("overwrite plus plus");
    }
  }); 

Full example: http://plnkr.co/edit/tAcv1F9y7t9q9XsQ1EFL?p=preview

I know that this would be probably better with directives, but is there any way to make it work with Controllers?

thanks for the help

like image 911
user1916783 Avatar asked Dec 12 '25 03:12

user1916783


1 Answers

  1. Don't try to access the DOM from controller code. Never. It is very bad practice which breaks AngularJS conventions and eventually provides you with bad architecture. This also means you should not create any DOM elements manually from a controller.

    Better to manipulate with the scope itself, not with its visual representation. You can add new models to scope on your button's click, which will be translated to new elements by ng-repeat directive, each with its own controller (remember controllers are instances, not singletons, so that they have separated life cycles).

  2. You might want to make use of <script type="text/ng-template"> and ng-include here instead of hidden divs.

  3. Try to avoid using $rootScope when possible - it is global state which can be dangerous.

It might look like this then (plunker):

HTML:

<div class="controller-a" ng-controller="ControllerA">
  Controller A
  <div>
    <button ng-click="cntPlusPlus()">cnt++</button> CNT: {{cnt}}
  </div>
  <button ng-click="addB()">Add B</button>
  <div ng-repeat="B in Bs">
   <div ng-include="'b-template'"></div>
  </div>
</div>
<script type="text/ng-template" id="b-template">
  <div ng-controller="ControllerB">this is controller b: <button ng-click="cntPlusPlus()">cnt++</button></div>
</script>

JS:

  var webApp = angular.module("webApp",[]);
  
  webApp.controller("ControllerA", function($scope){
    $scope.cnt = 0;
    $scope.cntPlusPlus = function(){
      $scope.cnt++;
    };
    
    $scope.Bs = [];
    $scope.addB = function(){
      $scope.Bs.push({});
    };
  });
  
  webApp.controller("ControllerB", function($scope){
    $scope.cntPlusPlus = function(){
      console.log("overwrite plus plus");
      $scope.$parent.$parent.$parent.cnt++;  //should be moved to service
    }
  });      
</script>
like image 64
artch Avatar answered Dec 14 '25 19:12

artch



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!