Jeremy Reed
Jeremy Reed

Reputation: 319

AngularJS scope of a directive in an include

How would I get my directive to update properly based on a variable on the parent of the parent's scope?

I have an animation directive that I want to use for showing loading for individual grids of data that will need to be populated by doing a service call. I currently have a main template for a page and I have an ng-include for a certain "widget" I want to show on the page. The widget will either show the div with the populated information or the loading directive will show, at least that's what I was trying to get it to do.

The $watch I have going on doesn't seem to be working either, i've put some log statements in there and I manually change the variable that "test" is pointing to, yet it acts as if it was never changed.

//One approach to the directive
myApp.directive('loading', function() {
    return {
        restrict: "E",
        scope : {
            test : '='
        },
        templateUrl: 'partials/loading-animation.html'
    };
});

The html for the include, which includes the directive also. loadVal is a variable on the scope of the parent's parent controller. loadVal changes based on a service call and is updated properly.

<div ng-show="!loadVal" class='address store'>
    <span>{{address.storeName}}</span>
    <span>{{address.address1}}</span>
    <span>{{address.city}},{{address.state}} {{address.zip}}</span>
</div>
<loading test="loadVal" ng-show="test"></loading>

Right now, if I just have the directive only, it still does not show up. I have tried it using ng-switch, but since there's no route change it shows both the loading directive and the address information. I've also tried showing either based on whether one is true or false (!loadVal and loadVal), the problem is though it doesn't seem to know what "!loadVal" is because it never displays the html that ng-show="!loadVal" is on.

Edit: Looks like I got it working just fine, here's a plnkr showing what I was trying to achieve: Plnkr

Note: I noticed I can't reference the parent of the parent's scope with ng-show (i.e ng-show="loadVal") on the directive template. However, if I make a new variable and have the scope be bi-directional and set that variable equal to loadVal, then it picks up the changes.

Upvotes: 0

Views: 354

Answers (1)

Justin Lovero
Justin Lovero

Reputation: 405

First of all, it appears that you are trying to access the test property of the loading directive's isolate scope in the ng-show directive. (<loading test="loadVal" ng-show="test"></loading>) That's not going to work. What ng-show is actually trying to bind to in your code is $scope.test in the parent scope. If you want to use the directive scope's test property for visibility, use it in your template.

Also, there is no need to use $watch in your directive as it stands right now and you should almost never need to use scope.$apply() for changes to scope properties. AngularJS wraps most of your code inside an $apply call for you.

Try this:

myApp.directive('loading', function() {
    return {
        restrict: "E",
        replace: true,
        scope : {
            test : '='
        },
        template: '<div ng-show="test"></div>'
    };
});

I replaced the templateUrl with an inline template just for demo purposes.

The loading directive in the view can be simplified to <loading test="loadVal"></loading>.

Upvotes: 1

Related Questions