1

I have the following Angular custom directive code:

Template (ReviewStandards.html)

<div class="review-standard" ng-repeat="standard in standards">
    <button ng-click="mark(standard)">Mark Complete</button>
</div>

JS

app.directive("reviewStandards", function ($parse, $state) {
return {
    restrict: "A",
    templateUrl: function (elements, attrs) {
        return "/Scripts/App/Directives/Templates/ReviewStandards.html";
    },
    transclude: false,
    scope: {
        standards: "="
    },
    replace: true,
    link: function (scope, elem, attrs) {

        scope.mark = function (standard) {
            alert();
        };
    }
  };
});

The directive is used as:

<div review-standards standards="review.ReviewStandards"></div>

Where standards is just a JSON array of standard objects.

Problem is that the the ng-click is not firing the function when the button is clicked. The scope is isolated - is this something to do with this or the fact that the button is in an ng-repeat?

12
  • How are you using directive inside ngRepeat? Commented Jun 21, 2016 at 6:47
  • Not sure I understand the question Commented Jun 21, 2016 at 6:48
  • How is <div review-standards standards="review.ReviewStandards"></div> related to the rest of the question? Commented Jun 21, 2016 at 6:48
  • 1
    try ng-click in controller controller: function($scope, $element){ $scope.click = function(){ } Commented Jun 21, 2016 at 6:52
  • 1
    dude, please remove replace: true,from your directive, you didn't need to replace that Commented Jun 21, 2016 at 7:03

2 Answers 2

6

Try This, "i just remove the Replace from your codes"

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

app.controller("ctrl", function($scope) {

  $scope.data = [{
      name: "a"
    },
    {
      name: "b"
    }
  ];


});

app.directive("reviewStandards", function() {
  var template = "<div class=\"review-standard\">" +
     "<div ng-repeat=\"standard in standards\">" +
      "{{standard.name}} " +
      "<button ng-click=\"mark(standard)\">Mark Complete</button>" +
     "<div><hr>" +
    "</div>";
  return {
    restrict: "A",
    transclude: false,
    template: template,
    scope: {
      standards: "="
    },
    link: function(scope, elem, attrs) {

      scope.mark = function(standard) {
        console.log(standard)
      };
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <div review-standards standards="data"></div>
</div>

Sign up to request clarification or add additional context in comments.

Comments

2

I'll try a bit explain why this happens.

Problems here with scope inheritance when using replace:true and in template just one element with ng-repeat.

If replace:false, template paste inside element with directive, so you get something like this

<div review-standards standards="review.ReviewStandards"> <!-- here isolated scope from review-standards directive -->
    <div class="review-standard" ng-repeat="standard in standards"> <!-- here child scope created with ng-repeat -->
        <button ng-click="mark(standard)">Mark Complete</button>
    </div>
</div>

So, child scopes that created by ng-repeat inherits from isolated scope review-standards directive, and all property from isolated scope available in children scopes.

When used replace:true, template replace element with directive, si you get something like this

<div class="review-standard" ng-repeat="standard in standards" review-standards standards="review.ReviewStandards"> <!-- here child scope created with ng-repeat -->
    <button ng-click="mark(standard)">Mark Complete</button>
</div>

And most interesting in this case, that now children scopes inherited from ng-controller, but $parent property setup to isolated scope review-standards directive. So in children scope available all properties from ng-controller scope but not available from isolated scope review-standards directive.

Simplest way for solution, as suggest in nearby answer, just remove replace:true

Yet another way: a bit change template, like this

<div>
    <div class="review-standard" ng-repeat="standard in standards">
        <button ng-click="mark(standard)">Mark Complete</button>
    </div>
</div>

Or a bit ugly solution: use $parent property instead hoping on inheritance

<div class="review-standard" ng-repeat="standard in $parent.standards">
    <button ng-click="$parent.mark(standard)">Mark Complete</button>
</div>

1 Comment

Thanks - is a comprehensive explanation of something that's not immediately apparent

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.