1

Is that a dynamic way to change ng-include controller?

My app allows users to create page some content and controllers. I can change ng-include src but I don't know how to dynamic associate a new controller. The following code isn't working:

<div ng-app="MyApp">
    <div ng-controller="ParentController">
        <select ng-model="currentItem" ng-options="item as item.url for item in items track by item.url">
        </select>
        {{ currentItem }}
        <div ng-include src="currentItem.url" ng-controller="currentItem.controller"></div>
    </div>
</div>

And I have the following JS:

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

app.controller('ParentController', ['$scope',function($scope){
    $scope.items = [{
        url: 'page1.html',
        controller: 'Page1Controller'
    },
    {
        url: 'page2.html',
        controller: 'Page2Controller'
    }];
    $scope.currentItem = {};
}]);

app.controller('Page1Controller', ['$scope',function(){
    alert('Page1');
}]);

app.controller('Page2Controller', ['$scope',function(){
    alert('Page2');
}]);
nanndoj
  • 6,580
  • 7
  • 30
  • 42

2 Answers2

3

I've done by using a directive instead:

<div ng-include src="currentItem.url" dyn-controller="currentItem.controller"></div>

JS Directive:

app.directive('dynController', ['$compile', '$parse',function($compile, $parse) {
  return {
    restrict: 'A',
    terminal: true,
    priority: 100000,
    link: function(scope, elem, attrs) {
            // Parse the scope variable
            var name = $parse(elem.attr('dyn-controller'))(scope);
            elem.removeAttr('dyn-controller');
            elem.attr('ng-controller', name);

            // Compile the element with the ng-controller attribute
            $compile(elem)(scope);       
  };
}]);

The trick here is watching for attribute changes, add ng-controller and then compile the element.

Thanks for

How to watch property in attrs of directive

and

Dynamic NG-Controller Name

Community
  • 1
  • 1
nanndoj
  • 6,580
  • 7
  • 30
  • 42
0

The following array of items is an array of plain objects that have two fields: url and controller, both containing string values.

 $scope.items = [{
        url: 'page1.html',
        controller: 'Page1Controller'
    },... ]

What you really need is a reference to the function and that can be achieved with the $injector service.

Eventough this might work, I don't get why you aren't using the ParentController to alter the object in your array (or a directive).

skubski
  • 1,586
  • 2
  • 19
  • 25
  • I'm not using `ParentController` because the the array of items and also the controller declaration, is dynamically created by my user. – nanndoj Jun 22 '15 at 13:15
  • Must have misinterpret your question. But you did state that this is the code you 'already' have. Nevertheless you're just binding a string instead of a controller function. – skubski Jun 22 '15 at 15:30