Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiate and initialize controller in AngularJS

I have a problem instanciating controller with Angular. I have a main controller AlkeTypeDefListController from which I want to dynamically create/remove controllers of type AlkeTypeDefController, so I have done that :

Code of AlkeTypeDefListController:

//  Create main controller          
Alke.controller('AlkeTypeDefListController', ['$scope', '$controller', function($scope, $controller)
{
    var primitives = 
    [

    ];

    //  Add some properties to the scope
    angular.extend($scope,
    {
        typedefs        : primitives,
        addTypeDef      : function()
        {            
            var controller = $controller("AlkeTypeDefController", {$scope:$scope.$new()});
            $scope.typedefs.push(controller);
        }             
    });   
}]);

Code of AlkeTypeDefController:

//  Create main controller          
Alke.controller('AlkeTypeDefController', ['$scope', '$controller', function($scope, $controller)
{
    //  Add some properties to the scope
    angular.extend($scope,
    {
        name            : "New Type",
        fields          : [],
        addField        : function()
        {

        }  
    });  
}]);

The html code is this one:

<div id="typedefs-editor" ng:controller="AlkeTypeDefListController">
    <button ng:click="addTypeDef()">Add</button>
    <button>Remove</button>
    <div id="typedef-list">
        <ul class="list">
        <li ng:repeat="typedef in typedefs"><a href="#">{{typedef.name}}</a></li>                               
        </ul>
    </div>
</div>

The problem does not really come from the instantiation (which works fine), but from the initialization. In fact, when the new "li" appears when I push the "Add" button, the text "New type" (initialized in the controller) does not appear.

I think it is about the scope or something like that, but I can't really find how to fix this.

I wanted to know if this method seems correct, and also how could I fix the problem I have.

Thanks

like image 868
dooxe Avatar asked Oct 01 '13 18:10

dooxe


People also ask

What are the controllers in AngularJS?

AngularJS Controllers AngularJS applications are controlled by controllers. The ng-controller directive defines the application controller. A controller is a JavaScript Object, created by a standard JavaScript object constructor.

What is $scope in AngularJS?

The $scope in an AngularJS is a built-in object, which contains application data and methods. You can create properties to a $scope object inside a controller function and assign a value or function to it. The $scope is glue between a controller and view (HTML).

Which is the correct syntax of creating a AngularJS controller?

13) Which of the following syntax is used to create a module in AngularJS? Answer: C is the correct option. To create a module in AngularJS, we use angular. module("app", []); syntax.

What is ng init in AngularJS?

The ng-init Directive is used to initialize AngularJS Application data. It defines the initial value for an AngularJS application and assigns values to the variables. The ng-init directive defines initial values and variables for an AngularJS application.


3 Answers

When you call $controller("AlkeTypeDefController") it will essentially call new on the AlkeTypeDefController constructor and give you back the return value not the scope. You are assign the name attrubute to the scope though so it is not being accessed in your html when you have typedef.name.

Try changing your AlkeTypeDefController to this:

Alke.controller('AlkeTypeDefController', function() {
    this.name = "New Type";
    this.fields = [];
    this.addField = function() {};
});

Then you can instantiate it with: var controller = $controller("AlkeTypeDefController"); and you shouldn't need to worry about creating nested scopes.

like image 29
rob Avatar answered Sep 21 '22 14:09

rob


If I get what you're saying correctly then I think I'd try to leverage the power of a custom directive here instead of dynamically generating controllers.

plunker

Controller:

Alke.controller('alkeTypeDefListController', ['$scope', '$controller',
  function($scope, $controller) {
    var primitives = [];
    var addTypeDef = function() {
      $scope.typedefs.push({
        name: 'new name'
      });
    };
    var removeTypeDef = function(){
      $scope.typedefs.pop();
    };

    var properties = {
      typedefs: primitives,
      addTypeDef: addTypeDef,
      removeTypeDef: removeTypeDef
    };

    //  Add some properties to the scope
    angular.extend($scope, properties);
  }
]);

Directive:

Alke.directive('alkeTypeDef', function() {
  return {
    restrict: 'A',
    scope: {
      typeDef: '=alkeTypeDef'
    },
    template: '<a href="#">{{typeDef.name}}</a>',
    link: function(scope, element, attr) {
      var properties = {
        fields: [],
        addField: function() {

        }
      };

      angular.extend(scope, properties);
    }
  };
});

HTML:

<div ng-app='Alke'>
  <div id="typedefs-editor" ng-controller="alkeTypeDefListController">
    <button ng-click="addTypeDef()">Add</button>
    <button ng-click="removeTypeDef()">Remove</button>
    <div id="typedef-list">
      <ul class="list">
        <li alke-type-def='typedef' ng-repeat="typedef in typedefs"></li>
      </ul>
    </div>
  </div>
</div>

If you want a controller then you can use one in the directive instead of a linking function.

like image 32
bmceldowney Avatar answered Sep 18 '22 14:09

bmceldowney


Reading the code, I understand that you want to create typedefs dynamically and those typedef items have to be controlled by an AlkeTypeDefController.

In that case I would create AlkeTypeDefController using ng:controller directive, so you don't need to create the controller programmatically, because then you would need to attached it to the view and that's just what the ngController directive does for you.

Notice AlkeTypeDefListController does not create a AlkeTypeDefController controller, this is done in the view

Demo on Plunker

Controllers:

.controller('AlkeTypeDefListController', ['$scope', function($scope) {
    var primitives = [];

    $scope.typedefs = primitives;

    $scope.addTypeDef = function() { 
      var typeDef = { name: 'New Type' };
      $scope.typedefs.push(typeDef);
    }
}])

.controller('AlkeTypeDefController', ['$scope', function($scope) {
    $scope.addField = function() {
      alert('add Field');
    }
}]);

View (notice how ng-controller directive is specified in li element):

<div id="typedefs-editor" ng:controller="AlkeTypeDefListController">
  <button ng:click="addTypeDef()">Add</button>
  <button>Remove</button>
  <div id="typedef-list">

  <ul class="list">
      <li ng:repeat="typedef in typedefs" ng:controller="AlkeTypeDefController">
        <a href="#" ng-click="addField()">{{typedef.name}}</a>            
      </li>                               
  </ul>
</div>

In the code above, ngRepeat is going to create a new $scope for each typedef. AlkeTypeDefController then decorates that scope with functions and values.

I hope it helps

like image 65
yeraycaballero Avatar answered Sep 20 '22 14:09

yeraycaballero