Search code examples
cssangularjsng-class

How do I change ng-class on window resize?


I have functionality where when I shrink the screen below a certain size and click on a table row it reveals other items in that table row. (white screen on left).

enter image description here

Then when I expand the window I want all table rows to return to normal, but I have a bug where if it's open already it won't close.
enter image description here

I tried setting the $scope.showIt variable to true/false, but it only seems to have an effect if it's the opposite of the initial $scope.showIt value. How do I change all the ng-classes in every td when the screen is a certain size?

This is my html:

<tr class="table-body  "ng-repeat="service in services | orderBy:myOrderBy | filter:search">
    <td align="center" valign="middle" ng-click="showIt = dropDetails(showIt)" ng-class="{'name-show':showIt, 'name-show-disabled':!showIt}">{{ service.name }}</td>
    <td  ng-class="{'show':showIt, 'show-disabled':!showIt}">{{ service.description }}</td>
    <td  ng-class="{'show':showIt, 'show-disabled':!showIt}">{{ service.prices }}</td>
</tr>

And in my controller:

$scope.dropDetails = function(showIt){ //This function works well. 
    console.log(window)     
    console.log(window.innerWidth)      
    if(window.innerWidth < 760){
        return !showIt;
    }else{
        return showIt;
    }

}

var w = angular.element($window);
var resizeId=0; 
$scope.showIt = true;

w.bind('resize ', function (a) {
        clearTimeout(resizeId);
        resizeId = setTimeout(function(){

        if(w[0].innerWidth < 760){

        }else{

            $scope.showIt = true;  //Does nothing. 
            $scope.$apply();

        }                   
        }, 500);
})

Solution

  • Do use Dot Rule while defining ng-model in Angular view. So that will help you to follow prototypal inheritance while refering to there property.

    The reason here is, you have used ng-repeat(which does create prototypically inherited child scope while rendering template each time on view). Here the same thing you need to do. Define model like $scope.model and inside that define showIt property. Rather you should put that showIt on each of you element of services, by which you handle each event individually.

    Markup

    <tr class="table-body" ng-repeat="service in services | orderBy:myOrderBy | filter:search">
        <td align="center" valign="middle" 
          ng-click="service.showIt= dropDetails(service.showIt)" 
          ng-class="{'name-show':service.showIt, 'name-show-disabled':!service.showIt}">
            {{ service.name }}
        </td>
        <td  ng-class="{'show':service.showIt, 'show-disabled':!service.showIt}">
           {{ service.description }}
        </td>
        <td  ng-class="{'show':service.showIt, 'show-disabled':!service.showIt}">
            {{ service.prices }}
        </td>
    </tr>
    

    Now question remains how to hide all the services, so that would be very easy. Loop through each services collection element & make showIt variable as false.

    angular.forEach($scope.services, function(service){
       service.showIt = false;
    })
    

    Also you are using custom event on DOM, I'd suggest you to put this code in directive. So that can get reusable too.