Squrler
Squrler

Reputation: 3514

How to show / hide a list of items with a button based on the number of items (Angular)

I have a list of items like:

    <ul>
      <li ng-repeat="show in data_shows">
        <span class="program_shows_show_day">{{show[2]*1000 | amDateFormat:'ddd D MMM'}}</span>
        <span class="program_shows_show_time">{{show[2]*1000 | amDateFormat:'H:mm'}} - {{show[3]*1000 | amDateFormat:'H:mm'}}</span>
      </li>
    </ul>

When there are more than 4 items I would like to show only the first 4 items and hide the rest with a button ('Show all').

With jQuery I would just count the items and if they're over 4 items apply a class to the <ul>. In Angular it's a bit more difficult- I know ng-repeat produces a $index variable, but I can only use that within the <li> items right? So what's the best way to apply a class on the <ul> element?

Upvotes: 0

Views: 5625

Answers (4)

gkalpak
gkalpak

Reputation: 48212

You can use Angular's limitTo filter to originally limit the number of displayed items to 4.

Additonally, you can have 2 buttons (one for showing all items, one for limiting the displayed items to 4) and show/hide them (or disable/enable them) according to the currently displayed items and the total number of items.

E.g.:

// VIEW
<ul>
    <li ng-repeat="item in items | limitTo:limit">{{item}}</li>
</ul>

<button ng-click="setLimit(4)" ng-disabled="(limit===4)||(items.length<=4)">
    Show few
</button>
<button ng-click="setLimit(0)" ng-disabled="items.length<=limit">
    Show all
</button>

// CONTROLLER
$scope.items = [...];
$scope.limit = 4;
$scope.setLimit = function (lim) {
    $scope.limit = (lim <= 0) ? $scope.items.length : lim;
};

See, also, this short demo.

Upvotes: 1

Mike Quinlan
Mike Quinlan

Reputation: 2882

ngClass is your best bet:

<ul ng-class="{'my-hiding-class': data_shows.length > 4}">
 ...

This just says add the class 'my-hiding-class' to the ul when your collection size is greater than 4. Documentation here

EDIT:

For the button you'd need to do something like this:

<button ng-click="toggleList()"></button>

Then in your directive:

scope.toggleList = function() {
  scope.showList = !scope.showList;
};

Then change your ngClass declaration slightly:

<ul ng-class="{'my-hiding-class': data_shows.length > 4 && showList}">

Edit 2:

Using the limitTo filter seems nice, but you might want to wrap it with custom functionality if you decide to go the filter route:

angular.module('myApp').filter('limitlessFilter', function($filter){
  return function(objects, limit, showAll) {
    if(showAll){
      return objects;
    } else {
      return $filter('limitTo')(objects, limit);
    }
  }
});

In your HTML:

<li ng-repeat="show in data_shows | limitlessFilter:4:showAll">
  ...

<button ng-bind="showAll && 'Show Less' || 'Show More'" ng-click="toggleShowAll()"></button>

In your controller/directive

scope.toggleShowAll = function() {
  scope.showAll = !scope.showAll;
};

On a side note, if you want to limit the number of renders your li go through, be sure to use track by on your ng-repeat. Documentation here

Upvotes: 4

JimminiKin
JimminiKin

Reputation: 46

This should do the trick

<ul>
  <li ng-repeat="show in data_shows | limitTo:4">
    <span class="program_shows_show_day">{{show[2]*1000 | amDateFormat:'ddd D MMM'}}</span>
    <span class="program_shows_show_time">{{show[2]*1000 | amDateFormat:'H:mm'}} - {{show[3]*1000 | amDateFormat:'H:mm'}}</span>
  </li>
</ul>
<button ng-hide="data_shows.length < 4">Show more</button>

You could replace the first "4" with a variable in your scope and modify this value when clicking the button.

But yeah, BenCr's answer sounds better in some ways.

Upvotes: 0

BenCr
BenCr

Reputation: 6042

Only add 4 items to your data_shows collection in your controller. That way you can test the logic, testing the view would be more tricky.

Upvotes: 0

Related Questions