Arashsoft
Arashsoft

Reputation: 2757

Access controller constructor by controller name in angular

I have a controller name as string and I want to get constructor of it.

My current method is using $controller as below:

$scope.myControllerConstructor= $controller( "myControllerName" , {$scope: $scope.$new()}).constructor;

Later on, I use this constructor in the html like this:

<div ng-controller="myControllerConstructor">

The issue is my controller runs two time, one time when I get the constructor (which is wrong) and one time when my html gets compiled (which is correct)

The question is how to get the controller constructor without running it?


Update about use-case: In our application we have many pages with 60% similarities and 40% different activities. I created a directive for those pages and other developers in the team are using my directive to create their page.

The directive accepts a template and a controller (I get them as string) and later on I include the provided template and controller as below:

<div ng-include="myTemplate" ng-controller="myControllerConstructor"></div>

Please take a look at this jsfiddle for a simple example of issue.

Upvotes: 1

Views: 731

Answers (2)

Maedeh HM
Maedeh HM

Reputation: 488

The structure of your code looks ok but the issue is $controller( "myControllerName" , {$scope: $scope.$new()}) already instantiate the controller with the given scope for you.

It is true that you can access the controller constructor with .constructor but it is too late as you already created an instance of the controller.

ng-controller does the exact same thing as $controller( "myControllerName" , {$scope: $scope.$new()})

When a Controller is attached to the DOM via the ng-controller directive, AngularJS will instantiate a new Controller object, using the specified Controller's constructor function. A new child scope will be created and made available as an injectable parameter to the Controller's constructor function as $scope.

To solve this issue you should pass the controller constructor function to pageDirectiveTemplate instead of the controller name.

The working fiddle

Upvotes: 1

tanmay
tanmay

Reputation: 7911

There is a different way we can achieve this. In directive, while using isolated scope (like you are doing here in fiddle), you could have a property controller that has value "@" and have another name property having the value of "myController" or whatever your controller name you are passing as.

So, your directive could look something like this:

app.directive('pageDirective', function() {
  return {
    restrict: "A",
    templateUrl: "pageDirectiveTemplate",
    scope: {
      myTemplate: "@"
    },
    controller: "@",
    name: "myController"
  }
});

Notice that, only change in HTML would be to have the directive as an attribute instead of an element. So,

<div page-directive my-template="templateA" my-controller="controllerA">
</div>
<div page-directive my-template="templateA" my-controller="controllerB">
</div>

This would give you exactly what you are looking for. Now you can have same template pointing different controllers and vice-versa.

working fiddle | Note that it works for two different controllers having same template. Also, check the console to see how it logs only once from each controller.

Upvotes: 0

Related Questions