angelokh
angelokh

Reputation: 9428

Migrated to AngularJs 1.3, child elements in ngRepeat not longer see directive's scope

In Angular 1.2, the element inside ngRepeat can see the parent scope's function(isConvoTabActive). However, after I switch to 1.3, this is no longer working. I checked the migration guide but found nothing. How can I fix this without using $parent.isConvoTabActive?

app.directive('myDirective',function(){
  return {
    restrict: 'E',
    scope: {
    },
    controller: ["$scope", "$element", "$attrs",
      function($scope, $element, $attrs) {
          $scope.isConvoTabActive = function(convoId) {           
            return convoId == $scope.indexes.activeConvoId;
          };
      }
    },
    template: "<div ng-repeat='(convoId, convo) in convos'>" +
                  "<div ng-if='isConvoTabActive(convoId)'></div>" +
              "</div>",
    replace: true, // replace the directive element
    link: function (scope, element, attrs) {
            scope.indexes = {
                "activeConvoId": "111"
            };
            scope.convos = {
               "111": {
                 "title": "convo 111" 
               },
               "222": {
                 "title": "convo 222"
               }
            };
    }       
  }
})

EDIT1 I tried ng-show, it doesn't work either.

EDIT2 It works on Plunker. I'm not sure why. http://plnkr.co/edit/7pdp40CQzUqOISwXgN4u

:

Upvotes: 1

Views: 396

Answers (3)

Nat Wallbank
Nat Wallbank

Reputation: 1457

OK, so this is an example of what I mean by using controller-as:

app.directive('myDirective',function() {
  return {
    restrict: 'E',
    scope: {
      indexes: '='
    },
    controllerAs: 'ctrl',
    bindToController: true,
    controller: function() {
      var model = this;
      model.isConvoTabActive = function(convo) {           
        return convo == model.indexes.activeConvo;
      };
    }
  },
  template: "<div ng-repeat='convo in ctrl.convos'>" +
              "<div ng-if='ctrl.isConvoTabActive(convo)'></div>" +
            "</div>"
  }
});

I've added this as another answer as formatting and space was limited in comments. I'm aware that I don't know where some things are coming from or what they contain, e.g. where does 'convos' get bound to scope? That's why I think a plunkr would be helpful. I've also made a change discussed in the other answer: to just compare the object references rather than ID values (gets problematic when value types are copied down the scope inheritance chain).

Upvotes: 0

Nat Wallbank
Nat Wallbank

Reputation: 1457

As an alternative solution, which would be less refactoring, you could just use ng-show (as long as you have no problem with your element being hidden from the DOM rather than removed). ng-show doesn't create a child scope.

Upvotes: 2

Nat Wallbank
Nat Wallbank

Reputation: 1457

You could use the controller as syntax which will allow you to reference your model / controller explicitly. I don't have a link handy on my phone or fancy typing a code example but it should be easy enough to find.

The bindToController property (for your directive) is key to getting rid of the need for $scope. It will bind your directive attributes to the controller instance instead.

Upvotes: 0

Related Questions