4

I've been trying to affect an variable in the parent scope to toggle ng-show from inside a directive. The directive is custom directive containing an ng-repeat directive. The idea, is that once the ng-repeat finishes, I want to hide the containing div as well as the elements inside of it.

Here's a Plunkr demonstrating my situation: http://beta.plnkr.co/edit/C42Z25?p=preview Also here's a comparison in JSFiddle, which uses the same problem, but it's not an ng-repeat and so it works: http://jsfiddle.net/dyzPC/

So there's several problems. Inside my directive, I have to use scope.$parent.showMe = true to change the parent scope's showMe, I can't seem to just use scope.showMe = true to set it. I tried with isolate scopes, no scopes, true scopes, nothing seems to work.

Furthermore, in a jquery callback function I cannot seem to reset the parent scope showMe as scope.$parent.showMe = false. This prevents me from showing the containing div when there's content, and hiding it when there's no content.

On a side note, one final problem is the usage of $last. In the plunkr example, using $last is possible, but in my real code, the ng-repeat collection is being filled up from an HTTP response interceptor. This seems to prevent $last from be used, as all the elements end up as $last = true. Is there a another way to detect when an ng-repeat has finished?

1

2 Answers 2

2

In your directive, you need to wrap scope.$parent.showMe = false; in scope.$apply():

scope.$parent.showMe = true; //this one works
element.hide().fadeIn('fast').delay(2000).fadeOut('slow', function(){
   scope.$apply(function(){
      scope.$parent.showMe = false;
   });
});

This is because you are changing the value of an Angular property outside of Angular (your jQuery function) so Angular doesn't know scope.showMe has changed.

You directive is in the same tag as your ngRepeat, you can't use an isolate scope as it would remove the bind for your ng-repeat="httpMessage in messages". In other words, httpMessages wouldn't exist if you isolated the scope here.

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

Comments

0

I would move the hide/show logic and the ng-repeat down into the directive, and then let the controller feed the directive the list of messages through the directive's attributes.

app.directive("hideShow", function() {
return {
    restrict: 'E',
    template: 
    "<div ng:repeat='message in messages'>" +
    "  <em>{{message.message}}</em> " +
    "</div>",
    scope: {
        messages: "="
    },
    link: function(scope, element, attrs) {
        element.hide();
        scope.$watch("messages", function() {
            element.fadeIn('fast').delay(1000).fadeOut('slow');               
        });
    }
};
});

Here's a working Fiddle.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.