Jevgeni
Jevgeni

Reputation: 2574

AngularJS, nested controllers from variable

Generally, what I want to do, is to initialize nested ng-controller inside ng-repeat using variable.

JSFiddle

JS

angular.module('app',[])
.controller('main',function($scope){
    angular.extend($scope,{
        name:'Parent Controller',
        items:[
            {name:'nested2'},
            {name:'nested1'}
            ]
    });
})
.controller('nested1',function($scope){
    $scope.name = "Name1";
})
.controller('nested2',function($scope){
    $scope.name = "Name2";
});

I want this:

<div ng-controller="main" ng-app='app'>
    Nested: {{name}}
    <div ng-controller="nested1">{{name}}</div>
    <div ng-controller="nested2">{{name}}</div>
</div>

to become to something like this:

<div ng-controller="main">
    Nested: {{name}}
    <div ng-repeat="item in items">
        <div ng-controller="item.name">{{name}}</div>
    </div>
</div>

Problem: it does not work this way. Neither it works any other way, that I've tried after google'ing for an hour or so.

Is there any "legal" and nice way to achieve that at all?

Upvotes: 0

Views: 604

Answers (2)

PSL
PSL

Reputation: 123739

There isn't a real way,using angular features it at this point, i suppose. You could create a directive and use un-documented dynamic controller feature controller:'@', name:'controllerName'. But this approach will not evaluate bindings or expressions that provide the controller name. What i can think of is a hack by instantiating a controller provided and setting it to the element.

Example:-

.directive('dynController', function($controller){
  return {
    scope:true, //create a child scope
    link:function(scope, elm, attrs){
      var ctrl =scope.$eval(attrs.dynController); //Get the controller
      ///Instantiate and set the scope
      $controller(ctrl, {$scope:scope})

     //Or you could so this  well
     //elm.data('$ngControllerController', $controller(ctrl, {$scope:scope}) ); 
    }
  }
});

And in your view:-

  <div ng-controller="main">
    <div ng-repeat="item in items">
    Nested:
          <div dyn-controller="item.name" ng-click="test()">{{name}}</div>
    </div>
  </div>

Demo

Note that i have changed the position of ng-controller from the element that does ng-repeat, since ng-repeat (1000) has higher priority than ng-controller (500), ng-repeat's scope will prevail and you end up not repeating anything.

While looking at it

Upvotes: 2

Jevgeni
Jevgeni

Reputation: 2574

Invested more couple hours into it, inspecting angular's sources etc.

The expression, given to ng-controller, is not being evaluated at all.

Here is best approach I've found:

HTML:

    <div ng-controller="main">
        Nested: {{name}}
        <div ng-repeat="item in items">
            <div ng-controller="nested" ng-init="init(item)">{{name}}</div>
        </div>
    </div>

JS:

angular.module('myApp', [])
    .controller('main', function ($scope, $controller) {
        angular.extend($scope, {
            name: 'Parent Controller',
            items: [
                {name: 'nested2'},
                {name: 'nested1'}
            ]
        });
    })
    .controller('nested', function ($scope, $controller) {
        angular.extend($scope, {
            init: function (item) {
                $controller(item.name, {'$scope': $scope});
            }
        });
    })
    .controller('nested1', function ($scope) {
        $scope.name = 'test1';
    })
    .controller('nested2', function ($scope) {
        $scope.name = 'test2';
    });

Upvotes: 1

Related Questions