Renaud is Not Bill Gates
Renaud is Not Bill Gates

Reputation: 2084

Implementing a "Load More" button to load more elements when its clicked

I want my li elements to be hidden and when my state loads I want to display only the first two elements and when I click on a button o show the next two elements and so on.

This is how it should work :

http://jsfiddle.net/zuyvgwx3/2/

In my angular application I display my li elements as following :

  <ul id="myList">
       <li ng-repeat="offre in offres |orderBy:'-dateCreation'|filter:{etat:'true'}">
         <div class="box">
            <!-- HTML Code -->
         </div>
      </li>
  </ul>

I have li elements set to display:none; and a javascript code that shows the first two elements as following :

<script>

    size_li = $("#myList li").size();
    x=2;
    $('#myList li:lt('+x+')').show();
    $('#loadMore').click(function () {
      x= x+2;
      $('#myList li:lt('+x+')').show();
    });

</script>

The problem is when my state loads all the li elements are shown and not only the first two elements, as you can see in the fiddle I attached it works but it doesn't work when I use it with ng-repeat.

How can I solve this?

Upvotes: 2

Views: 4606

Answers (4)

Rhumborl
Rhumborl

Reputation: 16609

As you are using Angular, you should try to avoid directly manipulating the DOM in this way where possible. Instead you should take advantage of Angular directives to control how elements are displayed, in this case ng-show.

You are already storing the list in the $scope.offres. You just need to keep track of how many items to show and only show it if the $index available in ng-repeat is lower than that value:

angular.module('myapp', []).controller('ctrl1', function($scope) {

  // set up the list with dummy data
  $scope.offres = [];
  for (var i = 0; i < 11; i++) {
    $scope.offres.push(i + 1);
  }

  // set initial index
  // we will use this variable to control the display - see ng-show="" in HTML
  $scope.loadIndex = 2;

  // function to increase visible items
  $scope.showMore = function() {
    // don't increment if at the end of the list
    if ($scope.loadIndex < $scope.offres.length) {
      $scope.loadIndex += 2;
    }
  };

  // function to decrease visible items
  $scope.showLess = function() {
    // don't decrement if at the start of the list
    if ($scope.loadIndex > 2) {
      $scope.loadIndex -= 2;
    }
  };
});
#loadMore {
  color: green;
  cursor: pointer;
}
#loadMore:hover {
  color: black;
}
#showLess {
  color: red;
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>


<div ng-app="myapp" ng-controller="ctrl1">
  <ul id="myList">
    <li ng-repeat="offre in offres" ng-show="$index < loadIndex">{{offre}}</li>
  </ul>
  <div id="loadMore" ng-click="showMore()">Load more</div>
  <div id="showLess" ng-click="showLess()">Show less</div>
</div>

As you can see, it is then trivial to implement showing less items, as you are just changing a number in your controller.

Upvotes: 1

Antoine Neff
Antoine Neff

Reputation: 456

As said by Rhumborl, you should use ng-show to handle this. When you click on the button, just increment a variable and show items only if variable > index.

<li ng-show="variable > index"></li>

$('#loadMore').click(function () {
  $scope.variable += 2;
});

Upvotes: 1

Vivek Athalye
Vivek Athalye

Reputation: 2979

When using AngularJS I personally try to avoid writing custom JQuery code for DOM manipulation. To implement the functionality that you have described, I would have taken following approach.

  1. Load the items in a temporary array, say offersHidden.
  2. When the items are loaded, shift() the 2 items from offersHidden and push() to offres
  3. When the user clicks on Load More, do the same thing: offres.push(offersHidden.shift())

That way you let AngularJS take care of UI manipulation and avoid any conflicts.

Upvotes: 1

Shashank Agrawal
Shashank Agrawal

Reputation: 25797

You can directly use Angular's ng-show/ng-hide and view binding to achieve this. You don't need to use jQuery for this. Here is a sample example:

var app = angular.module("sa", []);

app.controller("FooController", function($scope) {

  $scope.offers = [];

  // Generating dummy data
  for (var i = 0; i < 100; i++) {
    var number = i + 1;
    $scope.offers.push({
      number: number,
      name: 'Offer ' + number
    });
  }

  $scope.showFirstTwo = function() {
    var shown = 0;

    angular.forEach($scope.offers, function(offer) {
      if (!offer.isVisible && shown < 2) {
        offer.isVisible = true;
        shown++;
      }
    });
  };
  
  // At load, display first two by default
  $scope.showFirstTwo();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="sa" ng-controller="FooController">
  <ul>
    <li ng-repeat="offer in offers" ng-show="offer.isVisible">
      Offer ID: <strong>{{offer.number}}</strong>
      <br>Offer name: <strong>{{offer.name}}</strong>
    </li>
  </ul>
  
  <a href="" ng-click="showFirstTwo()">Load more</a>
</div>

Upvotes: 1

Related Questions