0

I am trying to follow from what I can tell so far is a pretty decent tutorial but I am a little stuck on a part where I need to create a directive to seperate a chunk of html and use a controller to generate the data.

var app = angular.module('newModule',[]);

app.directive('stateView', function(){
    return{
        restrict: 'E',
        templateUrl: 'state-view.html',
        controller: 'stateController',
        controllerAs: 'stateCtrl'
    }
});


 app.controller('stateController',function(){
     this.addStateTo = function(country){
         if(!country.states){
         country.states = [];
         }
         country.states.push({name: this.newState});
         this.newState = "";
     };
 });

My HTML stateview looks like this (C is a value from another controller to itterate through a list of other objects).

<div>
    <input type="text" name="state" ng-model="stateCtrl.newState">
    <a href ng-click="stateCtrl.addStateTo(c)"> Add State {{ stateCtrl.newState }}</a>
</div>

and the only HTML referrence I have on my index is the following:

<state-view></state-view>

It looks clean, but the problem is that it does not reconize the function addStateTo unless I tell the DIV element that it is the ng-controller called StateController. Isn't this what the directive is telling the HTML attribute?

3 Answers3

0

Try this instead ($scope instead of this):

app.controller('stateController',function($scope){
    $scope.addStateTo = function(country){
        if(!country.states){
          country.states = [];
        }
        country.states.push({name: this.newState});
        $scope.newState = "";
    };
});

OR

app.controller('stateController',function(){
    var vm = this;
    vm.addStateTo = function(country){
        if(!country.states){
          country.states = [];
        }
        country.states.push({name: this.newState});
        vm.newState = "";
    };
});
Arg0n
  • 8,283
  • 2
  • 21
  • 38
0

You are using the ControllerAs syntax and referencing the controller context appropriately (i.e. stateCtrl.newState and stateCtrl.addStateTo(c)). The problem is that you aren't creating the controller context properly. Your controller code should look like this:

app.controller('stateController', function() {
  var vm = this;

  this.addStateTo = function(country) {
    if (!country.states) {
      country.states = [];
    }
    country.states.push({
      name: vm.newState
    });
    vm.newState = "";
  };
});

Working example here

jbrown
  • 3,025
  • 1
  • 15
  • 22
  • The multiple runs are a result of the angular digest cycle executing more than once. There is no need to use the ng-controller directive in your HTML since you have already assigned the controller in your directive. Remove the ng-controller directive. – jbrown Jul 01 '16 at 12:34
  • I am almost inclined to sent the entire thing, because I dont get why this does not work as soon as I remove the ng-controller reference from the HTML element ><, as if he doesn't understand the scope of the function anymore. – HemlockDevelopment Jul 01 '16 at 12:46
  • When you say it doesn't work, do you mean that addStateTo() isn't being called or that there is an error when it is called? – jbrown Jul 01 '16 at 12:49
  • @HemlockDevelopment - I have modified my answer to include a link to a working example – jbrown Jul 01 '16 at 12:53
  • The function is not being called anymore as soon as I remove the attribute refference from the div tag. – HemlockDevelopment Jul 01 '16 at 12:53
  • @HemlockDevelopment - check out the working example in my answer to see how your code might be different than what I have working. – jbrown Jul 01 '16 at 12:54
  • Thanks for the example! That helped me figure out what the problem was. Apparently I was using a 1.1.5 version where this does not work? When I updated it to 1.5.6. I feel a little coding 101 fool right now :( – HemlockDevelopment Jul 01 '16 at 19:08
0

Try adding bindto controller true in your directive. And also the above answer is correct in fixing other issues you may run into, i.e mapping your this to the function, though at present not doing that may not cause a problem.

var app = angular.module('newModule',[]);

app.directive('stateView', function(){
    return{
        restrict: 'E',
        templateUrl: 'state-view.html',
        controller: 'stateController',
        controllerAs: 'stateCtrl',
        bindToController: true
    }
});


 app.controller('stateController',function(){
     var vm = this;
     vm.addStateTo = function(country){
         if(!country.states){
         country.states = [];
         }
         country.states.push({name: vm.newState});
         vm.newState = "";
     };
 });
Arathi Sreekumar
  • 2,544
  • 1
  • 17
  • 28