Destroying directives used in a ngRepeat

45 views
Skip to first unread message

Johan Smolders

unread,
Mar 17, 2014, 7:06:20 AM3/17/14
to ang...@googlegroups.com
I have a inbox kind of view which uses a ngRepeat.  Inside every row is a directive I created to mark the row (checkbox).
The problem is that when I use pagination and update the source of ngRepeat in every step the directives that are created in on every page aren't destroyed.
This means if you check on box on page one, one on page two and one on page three AngularJs thinks 3 items are selected.  
How do I destroy directives once they aren't shown anymore?

Luke Kende

unread,
Mar 18, 2014, 2:49:59 AM3/18/14
to ang...@googlegroups.com
It doesn't sound like the directive is the issue, but the object data in the array bound to ng-repeat.  I have a page that uses angular-ui-bootstrap's pager and the only items on the scope are the ones for the current page, hence I do not have this issue. 

What is the checkbox binding ng-model?  That is what you need to manage on paging, turn off any that aren't on the current page.  Make sense?

Sander Elias

unread,
Mar 18, 2014, 3:22:01 AM3/18/14
to ang...@googlegroups.com
hi Johan,

I suspect you are using $index to fill the checkboxes? Without seeing your code, it's hard to give you an answer on this. As Luke already said, it probably isn't the directive.
so Are you using $index? if yes, then there is your problem. If not, build a plunk/fiddle to show your problem, and one of us will help you fix it!

Regards
Sander

Johan Smolders

unread,
Mar 18, 2014, 4:27:10 AM3/18/14
to ang...@googlegroups.com
Hello Luke, Sander

Thanks for the reply. 
I'm not using the $index.  

Some simplified code:

I have a table created by ngRepeat:

<table class="table table-striped">
    <thead>
        <th>
            <div class="floating" resource-checkbox-all></div>
        </th>
        <th>Name</th>
        <th>Description</th>
        <th>Date </th>
    </thead>
    <tr ng-repeat="resource in resourceData.data">
        <td style="padding-right: 5px; vertical-align: middle"><div resource-checkbox="{{resource}}"></div></td>
        <td style="padding-right: 5px">{{resource.fullname}}</td>
        <td style="padding-right: 5px">{{resource.description}}</td>
        <td style="padding-right: 5px">{{resource.dateResource | javaTimeToGmailStyle }}</td>
    </tr>
</table>

The resource-checkbox code looks like this:

portalModule.directive('resourceCheckbox',  ['$rootScope', function ($rootScope) {
    var ResourceCheckboxController  = function ($scope, ResourceService) {
        $scope.isChecked = false;
        $scope.internalResource;
        $scope.checkResource = function($event){
            $event.stopPropagation();
            $scope.isChecked = !$scope.isChecked;
        }

        var readSelectedItems = $rootScope.$on("readSelectedItems", function (){
            if($scope.isChecked){
                ResourceService.readResource($scope.internalResource.id);
            }
        });

        var unreadSelectedItems = $rootScope.$on("unreadSelectedItems", function (){
            if($scope.isChecked){
                ResourceService.unreadResource($scope.internalResource.id);
            }
        });
    }

    return {
        restrict: 'A',
        template: '<input type="checkbox" ng-checked="isChecked" ng-click="checkResource($event)"></input>',
        controller: ResourceCheckboxController,
        link: function(scope, element, attrs){
            scope.internalResource =  JSON.parse(attrs.resourceCheckbox);
        }
    }
}]);


When I check one of the checkboxes on the first page and then navigate to page two resourceData.data in the ngRepeat segments update's and draws the new view.  All the resourceCheckboxes on page one get the destroy event. But when readSelectedItems is broadcasted the checkbox is selected on page one still seems to be responding to the broadcast and marks the line i checked on page one as read.  

I'm probably doing overlooking something silly, or maybe i'm not approaching this the right way. All help is welcome.

Thanks in advance.



--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/h5aiq09TKSQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.

Sander Elias

unread,
Mar 18, 2014, 4:40:09 AM3/18/14
to ang...@googlegroups.com
Hi Johan,

As far as I can see the code you just posted should work as expected. This code will give you all boxes unchecked by default. 
I think you left some the crucial part out when you simplified your  code.

Regards
Sander

Johan Smolders

unread,
Mar 18, 2014, 5:01:38 AM3/18/14
to ang...@googlegroups.com
Hi Sander,

I found a solution to the problem.
I added this to my directive:

 $scope.$on("$destroy",function() {
            readSelectedItems();
            unreadSelectedItems();
 });

This unregisters the rootScope listener from the directive scope.  
Can I derive from this behaviour that, although destroy is called on the directive, it isn't destroyed aslong as it has at least one listener attached to it? 
So I should be very carefull registering and unregistering $rootScope listeners?



--

Sander Elias

unread,
Mar 18, 2014, 7:36:18 AM3/18/14
to ang...@googlegroups.com
Hi Johan,

Yes, you should be really careful with the rootScope. All those warning you get about it, have their reasons :)

Regards
Sander

Johan Smolders

unread,
Mar 18, 2014, 8:02:55 AM3/18/14
to ang...@googlegroups.com
Hey Sander,

Thanks for the reply.  Do you have a better suggestion in handeling this kind of behaviour.
I'm trying to create a inbox type of interface just like your Gmail.

I use rootScope's broadcast to sent events between different directive's scopes.
(IE: directive with action on them, and the 'selection' directive itself').



--
Reply all
Reply to author
Forward
0 new messages