3gwebtrain
3gwebtrain

Reputation: 15303

angularjs using `ng-repeat` scope function not called

I am calling a method from the ng-repeat iterator. But i am not getting the method called in the scope. any one help me to sort this out?

here is my js :

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

app.controller('MainCtrl', function($scope) {

  $scope.levels = {'title':'Select a Level', item:["Low", "Medium", "Hight"], show:false };
  $scope.stages = ["Open", "Inprogress", "Closed"];
  $scope.colors = ["Red", "Yellow", "Blue"];

  $scope.levelHandler = function ( level ) {
    console.log( level ); //not called
  }

});


app.directive('dropDown', function () {

  return {

    replace:true,
    scope :{
      data:"="
    },
    template : $('#dropdown').html(),
    link:function (scope, element, attrs) {

      var title = element.find('.title');
      var listHolder = element.find('ul');
      var parent = title.add(listHolder);
      var list = element.find('li');

      title.on('click',  function (e) {
         scope.data.show = !scope.data.show;
         scope.$apply();

      });

      parent.add(listHolder).on('mouseleave',  function (e) {
         scope.data.show = !scope.data.show;
         scope.$apply();
      });


    }

  }

})

HTML :

<body ng-controller="MainCtrl">
    <form name="myform">

      <drop-down data="levels" ></drop-down>

    </form>
    <script type="text/ng-template" id="dropdown">

    <div class="formGroup">
        <h4 class="title">{{data.title}}</h4>
        <ul ng-show='data.show'>
          <li ng-repeat="level in data.item" ng-click="levelHandler( level )" >{{level}}</li>
        </ul>
      </div>

  </script>
  </body>

Live Demo

Upvotes: 0

Views: 311

Answers (2)

Duncan
Duncan

Reputation: 95652

You have an isolated scope inside your directive so you can't just refer to values in the scope outside. What you probably want here is to pass the levelHandler function into the dfirective:

app.directive('dropDown', function () {

  return {

    replace:true,
    scope :{
      data:"=",
      levelHandler: "="
    },
    template : $('#dropdown').html(),
    link:function (scope, element, attrs) {
...
})

and then in your html:

<drop-down data="levels" level-handler="levelHandler" ></drop-down>

an alternative would be to not use an isolated scope at all but just access data through attrs.data. This has the disadvantage that if it's an expression you have to evaluate it your self, but it can sometimes be preferable.

BTW, it is usually better to use ng-click and ng-mouseleave in your template rather than binding the events. That way you never have to worry about calling scope.$apply() for yourself.

Upvotes: 1

Nitsan Baleli
Nitsan Baleli

Reputation: 5458

your directive has an isolated scope, therefore you'll need to bind the outside function from the controller into the directive, and it'll work as expected.

here's a working plnkr

scope :{
    data:"=",
    func: '='
}

template:

<drop-down func='levelHandler' data="levels" ></drop-down>
..
<li ng-repeat="level in data.item" ng-click="func( level )" >{{level}}</li>

here's a nice tutorial that explains directive scope

Upvotes: 1

Related Questions