sid
sid

Reputation: 1

auto creating instance of controller in angularjs

I'm trying to automatically create an instance of 'loadPlugCtrl' as may times as directive is used, but it's not working. You can see it's printing the same label twice where as they should be different. One more thing I noticed that in directive the command

console.log(ctrlInstName);

is getting executed only once. I have no idea what's happening here.

// Code goes here
angular.module('plunker', ['loadPlugin']);

function randomString(length) {
    chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    var result = '';
    for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
    return result;
}

angular.module('loadPlugin', [])
.directive("loadPlugin", ['$compile', function($compile){
  
  var ctrlInstName = "loadPluginCtrl_" + randomString(8);
  console.log(ctrlInstName);
  
  return{
    restrict: 'E',
    replace: true,
    controller: "loadPluginCtrl",
    controllerAs:ctrlInstName,
      link: function(scope, element, attrs) {
         
        scope.label = randomString(attrs.plug);
        var template = '<p>{{label}}</p>';
        var linkFn = $compile(template);
        var content = linkFn(scope);
        element.append(content);
        
      } // End link
    }; // End return
}])
.controller("loadPluginCtrl", ['$scope', function($scope) {
  // This controller should be instantiated as many times
  // as the directive is used in HTML.
}]);
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="style.css">
    <script data-require="[email protected]" src="https://code.angularjs.org/1.6.4/angular.js" data-semver="1.6.4"></script>
    <script src="script.js"></script>
  </head>

  <body>
    <p>Test</p>
    <load-plugin plug="15"></load-plugin>
    <load-plugin plug="20"></load-plugin>
  </body>

</html>

Let me explain you guys, what actually I am trying to do. I have n number of form templates stored on server along with their data in database. All most all of the features required to handle forms has been written in a controller. Let's say it's a base controller for all of them.

  1. Load the form template dynamically along with it's data using GET service.
  2. Automatically assign base controller's instance to it.

I am aware of the face that Angular is designed for SPA but my requirement is more of website like. I was wrong when thought I could achieve this using directive.

I would be glad if some one point me the right direction to do.

Upvotes: 0

Views: 267

Answers (2)

charlietfl
charlietfl

Reputation: 171698

Each instance of directive will create a new controller instance.... but there is only one registration of the directive itself within the module

If you use controllerAs you want to assign values to the controller object not $scope and there is no benefit in creating a dynamic controller alias name:

angular.module('loadPlugin', [])
  .directive("loadPlugin", ['$compile', function($compile) {
    return {
      restrict: 'E',
      replace: true,
      controller: "loadPluginCtrl",
      //scope: {},
      template: '<p>{{$ctrl.label}}</p>',
      controllerAs: '$ctrl',
      link: function(scope, element, attrs, ctrl) {
          ctrl.label = randomString(attrs.plug);
      } // End link
    }; // End return
  }])
  .controller("loadPluginCtrl", ['$scope', function($scope) {
    var vm = this;
    // demonstrate that each use creates own instance of controller
    $scope.$watch(function(){
      return vm.label;
    }, function(nVal) {         
      if (nVal) {
        console.log('Label for this instance is:', nVal)
      }
    })
  }]);

DEMO

Upvotes: 0

Estus Flask
Estus Flask

Reputation: 223249

A controller is instantiated each time when a directive is compiled, this is what it is for.

The problem is that you picked the wrong way to test this. Directive factory function is executed only once. That's why ctrlInstName never changes. All controller-specific code should be put to controller.

Dynamic controllerAs property is not possible and is a design mistake.

Upvotes: 1

Related Questions