View on GitHub

blog

Here are the labs from my blog.

JavaEE AngularJS Bootstrap: How to Pagination with Smart-Table

alt text

A paginated data-table with a back-end inspired by Spring-Data Repository pattern implementation and front-end using Bootstrap pagination and ng-module Smart-Table.

Note: there are two famous ng-modules. Ng-Table and SmartTable. Ng-table has a lot of stars on ngmodules.org but I choose Smart-Table instead because it’s latest version is in maven repositories (183 vs 35 stars on ngmodules.org, but 2014 jar vs 2015 on mvnrepository.com).

Demo

http://localhost:8080/20151102-javaee-angularjs-bootstrap-pagination/ http://localhost:8080/20151102-javaee-angularjs-bootstrap-pagination/

A data-table with page size selector (10, 25, 50) and pagination bar (1,2,3,4,5,>,LAST)

alt text

Data-table’s page size can be change to 25 or 50.

alt text

The displayed page can be change to another (2 here).

alt text

It’s also possible to jump to First or Last page.

alt text

Source

alt text

DatasRepository.java

package com.damienfremont.blog;
 
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.PagingAndSortingRepository;
import com.damienfremont.blog.ServiceJAXRS.Person;
 
public class DatasRepository implements PagingAndSortingRepository<Person, Serializable> {
 
  // MOCK
  static List<Person> datas;
  static {
    datas = new ArrayList<>();
    for (int i = 0; i < 5000; i++) {
      datas.add(new Person(i + 1, "John", "Doe"));
      i++;
      datas.add(new Person(i + 1, "Mich", "Jogger"));
      i++;
      datas.add(new Person(i + 1, "Santa", "Close"));
    }
  }
 
  @Override
  public Page<Person> findAll(Pageable arg0) {
    int pSize = arg0.getPageSize();
    int pNumb = arg0.getPageNumber();
    int pFirst = pNumb * pSize;
    int pLast = pFirst + pSize;
    int total = datas.size();
    List<Person> content = new ArrayList<>();
    for (int i = 0; i < total; i++) { if (i >= pFirst && i < pLast) {
        Person data = datas.get(i);
        content.add(data);
      }
    }
    return new PageImpl<>(content, arg0, total);
  }
  ...
}

MyAppCONFIG.java

package com.damienfremont.blog;
 
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
 
public class MyAppCONFIG extends Application {
 
  @Override
  public Set<Class<?>> getClasses() {
    Set<Class<?>> s = new HashSet<Class<?>>();
    s.add(ServiceJAXRS.class);
    return s;
  }
}

ServiceJAXRS.java

package com.damienfremont.blog;
 
import java.io.Serializable;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
 
@Path("/person")
public class ServiceJAXRS {
 
  DatasRepository datas = new DatasRepository();
 
  @Path("/page")
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public Page<Person> getAll( //
      @QueryParam("sort") String sort, //
      @QueryParam("page") Integer page, //
      @QueryParam("size") Integer size) {
    Pageable pageRequest = new PageRequest( //
        ((page == null) ? 0 : (page-1)), //
        ((size == null) ? 10 : size));
    return datas.findAll(pageRequest);
  }
 
  // MODEL
  static class Person implements Serializable {
    private static final long serialVersionUID = 9167120287441116359L;
    public Integer id;
    public String firstName;
    public String lastName;
 
    public Person() {
 
    }
 
    public Person(Integer id, String firstName, String lastName) {
      super();
      this.id = id;
      this.firstName = firstName;
      this.lastName = lastName;
    }
  }
 
}

web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
 
    <servlet>
        <servlet-name>REST</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.damienfremont.blog.MyAppCONFIG</param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.server.provider.classnames</param-name>
            <param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>REST</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>
 
    <servlet>
        <servlet-name>WEBJARS</servlet-name>
        <servlet-class>org.webjars.servlet.WebjarsServlet</servlet-class>
        <init-param>
            <param-name>disableCache</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>WEBJARS</servlet-name>
        <url-pattern>/webjars/*</url-pattern>
    </servlet-mapping>
 
</web-app>

app.js

'use strict';
 
var app = angular.module(
  'app',
  [ 'ngResource',
    'smart-table'
    ]);
 
app.factory('Service', function($resource) {
    return $resource('api/person/page');
});
 
app.controller('TableCtrl', function ($scope, Service) {
     
  $scope.itemsByPage = 10;
     
  $scope.callServer = function(tableState) {
    $scope.isLoading = true;
    var pagination = tableState.pagination;
    var start = pagination.start || 0;
    var number = pagination.number || $scope.itemsByPage;
    Service.get({
      page : 1+(start/number),
      size : number
      },
      function(pageable) {
        $scope.pageable = pageable;
        $scope.items = pageable.content;
        tableState.pagination.numberOfPages = pageable.totalPages;
        $scope.isLoading = false;
    });
  };
});

index.jsp

<!DOCTYPE html>
<html ng-app="app">
<head>
<!-- LIBS CSS -->
<link rel="stylesheet" href="webjars/bootstrap/${bootstrap.version}/css/bootstrap.css">
<!-- LIBS JS -->
<script src="webjars/angularjs/${angularjs.version}/angular.js"></script>
<script src="webjars/angularjs/${angularjs.version}/angular-resource.js"></script>
<script src="webjars/angular-smart-table/${angular-smart-table.version}/dist/smart-table.js"></script>
<!-- YOUR JS -->
<script src="app.js"></script>
</head>
<body>
<div class="container">
<h1>Pagination</h1>
<form ng-controller="TableCtrl">
<table class="table"
  st-table="items"
  st-pipe="callServer">
<thead>
 
<!-- PAGE SIZE -->
<tr>
  <td colspan="3">
    <div class="btn-group pull-right ng-scope">
      <button type="button"
        ng-class="{'active':itemsByPage==10}"
        ng-click="itemsByPage=10"
        class="btn btn-default">10</button>
      <button type="button"
        ng-class="{'active':itemsByPage==25}"
        ng-click="itemsByPage=25"
        class="btn btn-default">25</button>
      <button type="button"
        ng-class="{'active':itemsByPage==50}"
        ng-click="itemsByPage=59"
        class="btn btn-default">50</button>
    </div>
  </td>
</tr>
     
<!-- HEADERS -->
<tr>
  <th>#</th>
  <th>First Name</th>
  <th>Last Name</th>
</tr>
</thead>
 
<!-- CONTENT -->
<tbody>
<tr ng-repeat="i in items">
  <td></td>
  <td></td>
  <td></td>
</tr>
</tbody>
 
<!-- PAGINATION -->
<tfoot>
<tr>
  <td colspan="3" class="text-center">
    <div
      st-template="pagination.html"
      st-pagination=""
      st-items-by-page="itemsByPage"></div>
  </td>
</tr>
</tfoot>
</table>
</form>   
</div>
</body>
</html>

pagination.html

<div class="pagination" ng-if="pages.length >= 2">
  <ul class="pagination">
    <li ng-if="currentPage > 1">
      <a ng-click="selectPage(1)" href="#1">
        FIRST</a></li>
    <li ng-if="currentPage > 1">
      <a ng-click="selectPage(currentPage-1)" href="#">
        &lt;</a></li>
    <li ng-repeat="page in pages" ng-class="{active: page==currentPage}">
      <a ng-click="selectPage(page)" href="#{"permalink"=>"/20151102-javaee-angularjs-bootstrap-pagination/", "layout"=>"default", "title"=>"JavaEE AngularJS Bootstrap: How to Pagination with Smart-Table", "content"=>"JavaEE AngularJS Bootstrap: How to Pagination with Smart-Table\n======\n \n![alt text](/blog/20151102-javaee-angularjs-bootstrap-pagination/screenshots/160523003531333.png)\n \n\n \nA paginated data-table with a back-end inspired by Spring-Data Repository pattern implementation and front-end using Bootstrap pagination and ng-module Smart-Table.\n\nNote: there are two famous ng-modules. Ng-Table and SmartTable. Ng-table has a lot of stars on ngmodules.org but I choose Smart-Table instead because it’s latest version is in maven repositories (183 vs 35 stars on ngmodules.org, but 2014 jar vs 2015 on mvnrepository.com).\n \n# Demo\n \n[http://localhost:8080/20151102-javaee-angularjs-bootstrap-pagination/](http://localhost:8080/20151102-javaee-angularjs-bootstrap-pagination/)\nhttp://localhost:8080/20151102-javaee-angularjs-bootstrap-pagination/\n \nA data-table with page size selector (10, 25, 50) and pagination bar (1,2,3,4,5,>,LAST)\n \n![alt text](/blog/20151102-javaee-angularjs-bootstrap-pagination/screenshots/160523003531407.png)\n \n\n \nData-table’s page size can be change to 25 or 50.\n \n![alt text](/blog/20151102-javaee-angularjs-bootstrap-pagination/screenshots/160523003531930.png)\n \n\n \nThe displayed page can be change to another (2 here).\n \n![alt text](/blog/20151102-javaee-angularjs-bootstrap-pagination/screenshots/160523003531960.png)\n \n\n \nIt’s also possible to jump to First or Last page.\n \n![alt text](/blog/20151102-javaee-angularjs-bootstrap-pagination/screenshots/160523003531986.png)\n \n\n \n# Source\n \n![alt text](/blog/20151102-javaee-angularjs-bootstrap-pagination/screenshots/160523003532015.png)\n \n\n \nDatasRepository.java\n \n```java\npackage com.damienfremont.blog;\n \nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.PageImpl;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.domain.Sort;\nimport org.springframework.data.repository.PagingAndSortingRepository;\nimport com.damienfremont.blog.ServiceJAXRS.Person;\n \npublic class DatasRepository implements PagingAndSortingRepository<Person, Serializable> {\n \n  // MOCK\n  static List<Person> datas;\n  static {\n    datas = new ArrayList<>();\n    for (int i = 0; i < 5000; i++) {\n      datas.add(new Person(i + 1, \"John\", \"Doe\"));\n      i++;\n      datas.add(new Person(i + 1, \"Mich\", \"Jogger\"));\n      i++;\n      datas.add(new Person(i + 1, \"Santa\", \"Close\"));\n    }\n  }\n \n  @Override\n  public Page<Person> findAll(Pageable arg0) {\n    int pSize = arg0.getPageSize();\n    int pNumb = arg0.getPageNumber();\n    int pFirst = pNumb * pSize;\n    int pLast = pFirst + pSize;\n    int total = datas.size();\n    List<Person> content = new ArrayList<>();\n    for (int i = 0; i < total; i++) { if (i >= pFirst && i < pLast) {\n        Person data = datas.get(i);\n        content.add(data);\n      }\n    }\n    return new PageImpl<>(content, arg0, total);\n  }\n  ...\n}\n```\n \nMyAppCONFIG.java\n \n```java\npackage com.damienfremont.blog;\n \nimport java.util.HashSet;\nimport java.util.Set;\nimport javax.ws.rs.core.Application;\n \npublic class MyAppCONFIG extends Application {\n \n  @Override\n  public Set<Class<?>> getClasses() {\n    Set<Class<?>> s = new HashSet<Class<?>>();\n    s.add(ServiceJAXRS.class);\n    return s;\n  }\n}\n```\n \nServiceJAXRS.java\n \n```java\npackage com.damienfremont.blog;\n \nimport java.io.Serializable;\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.Produces;\nimport javax.ws.rs.QueryParam;\nimport javax.ws.rs.core.MediaType;\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.PageRequest;\nimport org.springframework.data.domain.Pageable;\n \n@Path(\"/person\")\npublic class ServiceJAXRS {\n \n  DatasRepository datas = new DatasRepository();\n \n  @Path(\"/page\")\n  @GET\n  @Produces(MediaType.APPLICATION_JSON)\n  public Page<Person> getAll( //\n      @QueryParam(\"sort\") String sort, //\n      @QueryParam(\"page\") Integer page, //\n      @QueryParam(\"size\") Integer size) {\n    Pageable pageRequest = new PageRequest( //\n        ((page == null) ? 0 : (page-1)), //\n        ((size == null) ? 10 : size));\n    return datas.findAll(pageRequest);\n  }\n \n  // MODEL\n  static class Person implements Serializable {\n    private static final long serialVersionUID = 9167120287441116359L;\n    public Integer id;\n    public String firstName;\n    public String lastName;\n \n    public Person() {\n \n    }\n \n    public Person(Integer id, String firstName, String lastName) {\n      super();\n      this.id = id;\n      this.firstName = firstName;\n      this.lastName = lastName;\n    }\n  }\n \n}\n```\n \nweb.xml\n \n```xml\n<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd\" version=\"3.1\">\n \n    <servlet>\n        <servlet-name>REST</servlet-name>\n        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>\n        <init-param>\n            <param-name>javax.ws.rs.Application</param-name>\n            <param-value>com.damienfremont.blog.MyAppCONFIG</param-value>\n        </init-param>\n        <init-param>\n            <param-name>jersey.config.server.provider.classnames</param-name>\n            <param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>\n        </init-param>\n        <load-on-startup>1</load-on-startup>\n    </servlet>\n    <servlet-mapping>\n        <servlet-name>REST</servlet-name>\n        <url-pattern>/api/*</url-pattern>\n    </servlet-mapping>\n \n    <servlet>\n        <servlet-name>WEBJARS</servlet-name>\n        <servlet-class>org.webjars.servlet.WebjarsServlet</servlet-class>\n        <init-param>\n            <param-name>disableCache</param-name>\n            <param-value>true</param-value>\n        </init-param>\n        <load-on-startup>2</load-on-startup>\n    </servlet>\n    <servlet-mapping>\n        <servlet-name>WEBJARS</servlet-name>\n        <url-pattern>/webjars/*</url-pattern>\n    </servlet-mapping>\n \n</web-app>\n```\n \napp.js\n \n```javascript\n'use strict';\n \nvar app = angular.module(\n  'app',\n  [ 'ngResource',\n    'smart-table'\n    ]);\n \napp.factory('Service', function($resource) {\n    return $resource('api/person/page');\n});\n \napp.controller('TableCtrl', function ($scope, Service) {\n     \n  $scope.itemsByPage = 10;\n     \n  $scope.callServer = function(tableState) {\n    $scope.isLoading = true;\n    var pagination = tableState.pagination;\n    var start = pagination.start || 0;\n    var number = pagination.number || $scope.itemsByPage;\n    Service.get({\n      page : 1+(start/number),\n      size : number\n      },\n      function(pageable) {\n        $scope.pageable = pageable;\n        $scope.items = pageable.content;\n        tableState.pagination.numberOfPages = pageable.totalPages;\n        $scope.isLoading = false;\n    });\n  };\n});\n```\n \nindex.jsp\n \n```xml\n<!DOCTYPE html>\n<html ng-app=\"app\">\n<head>\n<!-- LIBS CSS -->\n<link rel=\"stylesheet\" href=\"webjars/bootstrap/${bootstrap.version}/css/bootstrap.css\">\n<!-- LIBS JS -->\n<script src=\"webjars/angularjs/${angularjs.version}/angular.js\"></script>\n<script src=\"webjars/angularjs/${angularjs.version}/angular-resource.js\"></script>\n<script src=\"webjars/angular-smart-table/${angular-smart-table.version}/dist/smart-table.js\"></script>\n<!-- YOUR JS -->\n<script src=\"app.js\"></script>\n</head>\n<body>\n<div class=\"container\">\n<h1>Pagination</h1>\n<form ng-controller=\"TableCtrl\">\n<table class=\"table\"\n  st-table=\"items\"\n  st-pipe=\"callServer\">\n<thead>\n \n<!-- PAGE SIZE -->\n<tr>\n  <td colspan=\"3\">\n    <div class=\"btn-group pull-right ng-scope\">\n      <button type=\"button\"\n        ng-class=\"{'active':itemsByPage==10}\"\n        ng-click=\"itemsByPage=10\"\n        class=\"btn btn-default\">10</button>\n      <button type=\"button\"\n        ng-class=\"{'active':itemsByPage==25}\"\n        ng-click=\"itemsByPage=25\"\n        class=\"btn btn-default\">25</button>\n      <button type=\"button\"\n        ng-class=\"{'active':itemsByPage==50}\"\n        ng-click=\"itemsByPage=59\"\n        class=\"btn btn-default\">50</button>\n    </div>\n  </td>\n</tr>\n     \n<!-- HEADERS -->\n<tr>\n  <th>#</th>\n  <th>First Name</th>\n  <th>Last Name</th>\n</tr>\n</thead>\n \n<!-- CONTENT -->\n<tbody>\n<tr ng-repeat=\"i in items\">\n  <td>{{i.id}}</td>\n  <td>{{i.firstName}}</td>\n  <td>{{i.lastName}}</td>\n</tr>\n</tbody>\n \n<!-- PAGINATION -->\n<tfoot>\n<tr>\n  <td colspan=\"3\" class=\"text-center\">\n    <div\n      st-template=\"pagination.html\"\n      st-pagination=\"\"\n      st-items-by-page=\"itemsByPage\"></div>\n  </td>\n</tr>\n</tfoot>\n</table>\n</form>   \n</div>\n</body>\n</html>\n```\n \npagination.html\n \n```xml\n<div class=\"pagination\" ng-if=\"pages.length >= 2\">\n  <ul class=\"pagination\">\n    <li ng-if=\"currentPage > 1\">\n      <a ng-click=\"selectPage(1)\" href=\"#1\">\n        FIRST</a></li>\n    <li ng-if=\"currentPage > 1\">\n      <a ng-click=\"selectPage(currentPage-1)\" href=\"#\">\n        &lt;</a></li>\n    <li ng-repeat=\"page in pages\" ng-class=\"{active: page==currentPage}\">\n      <a ng-click=\"selectPage(page)\" href=\"\#{{page}}\">\n        {{page}}</a></li>\n    <li ng-if=\"currentPage < numPages\">\n      <a ng-click=\"selectPage(currentPage+1)\" href=\"#\">\n        &gt;</a></li>\n    <li ng-if=\"currentPage < numPages\">\n      <a ng-click=\"selectPage(numPages)\" href=\"\#{{numPages}}\">\n        LAST</a></li>\n  </ul>\n</div>\n```\n \npom.xml\n \n```xml\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n \n  <groupId>com.damienfremont.blog</groupId>\n  <artifactId>20151102-javaee-angularjs-bootstrap-pagination</artifactId>\n  <version>0.0.1-SNAPSHOT</version>\n  <packaging>war</packaging>\n \n  <properties>\n    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n    <!-- JAVAEE -->\n    <java.version>7</java.version>\n    <javaee.version>7.0</javaee.version>\n    <jersey.version>2.22.1</jersey.version>\n    <!-- WEB -->\n    <bootstrap.version>3.3.5</bootstrap.version>\n    <angularjs.version>1.4.7</angularjs.version>\n    <angular-ui-bootstrap.version>0.14.0</angular-ui-bootstrap.version>\n    <angular-smart-table.version>2.1.4</angular-smart-table.version>\n  </properties>\n \n  <dependencies>\n \n    <!-- JAVA -->\n \n    <dependency>\n      <groupId>javax</groupId>\n      <artifactId>javaee-api</artifactId>\n      <version>${javaee.version}</version>\n      <scope>provided</scope>\n    </dependency>\n \n    <dependency>\n      <groupId>org.glassfish.jersey.containers</groupId>\n      <artifactId>jersey-container-servlet</artifactId>\n      <version>${jersey.version}</version>\n    </dependency>\n    <dependency>\n      <groupId>org.glassfish.jersey.media</groupId>\n      <artifactId>jersey-media-json-jackson</artifactId>\n      <version>${jersey.version}</version>\n    </dependency>\n \n    <dependency>\n      <groupId>org.springframework.data</groupId>\n      <artifactId>spring-data-commons</artifactId>\n      <version>1.9.0.RELEASE</version>\n    </dependency>\n \n \n    <!-- WEB -->\n \n    <dependency>\n      <groupId>org.webjars</groupId>\n      <artifactId>webjars-servlet-2.x</artifactId>\n      <version>1.1</version>\n    </dependency>\n \n    <dependency>\n      <groupId>org.webjars</groupId>\n      <artifactId>angularjs</artifactId>\n      <version>${angularjs.version}</version>\n    </dependency>\n    <dependency>\n      <groupId>org.webjars</groupId>\n      <artifactId>angular-ui-bootstrap</artifactId>\n      <version>${angular-ui-bootstrap.version}</version>\n    </dependency>\n    <dependency>\n      <groupId>org.webjars.bower</groupId>\n      <artifactId>angular-smart-table</artifactId>\n      <version>${angular-smart-table.version}</version>\n    </dependency>\n \n    <dependency>\n      <groupId>org.webjars</groupId>\n      <artifactId>bootstrap</artifactId>\n      <version>${bootstrap.version}</version>\n    </dependency>\n \n  </dependencies>\n  <build>\n    <resources>\n      <resource>\n        <directory>src/main/webapp</directory>\n        <filtering>true</filtering>\n        <targetPath>${project.basedir}/target/m2e-wtp/web-resources</targetPath>\n        <includes>\n          <include>*.jsp</include>\n        </includes>\n      </resource>\n    </resources>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-war-plugin</artifactId>\n        <version>2.6</version>\n        <configuration>\n          <webResources>\n            <resource>\n              <directory>src/main/webapp</directory>\n              <filtering>true</filtering>\n              <includes>\n                <include>*.jsp</include>\n              </includes>\n            </resource>\n          </webResources>\n        </configuration>\n      </plugin>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-compiler-plugin</artifactId>\n        <version>3.1</version>\n        <configuration>\n          <source>1.${java.version}</source>\n          <target>1.${java.version}</target>\n        </configuration>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n```\n \n# Project\n \n[https://github.com/DamienFremont/blog/tree/master/20151102-javaee-angularjs-bootstrap-pagination](https://github.com/DamienFremont/blog/tree/master/20151102-javaee-angularjs-bootstrap-pagination)\nhttps://github.com/DamienFremont/blog/tree/master/20151102-javaee-angularjs-bootstrap-pagination\n \n# References\n \n[http://projects.spring.io/spring-data/](http://projects.spring.io/spring-data/)\nhttp://projects.spring.io/spring-data/\n \n[http://ngmodules.org/modules/Smart-Table](http://ngmodules.org/modules/Smart-Table)\nhttp://ngmodules.org/modules/Smart-Table\n \n[http://lorenzofox3.github.io/smart-table-website/](http://lorenzofox3.github.io/smart-table-website/)\nhttp://lorenzofox3.github.io/smart-table-website/\n \n[http://plnkr.co/edit/e82rdx7R4pjbLvayUHXx?p=preview](http://plnkr.co/edit/e82rdx7R4pjbLvayUHXx?p=preview)\nhttp://plnkr.co/edit/e82rdx7R4pjbLvayUHXx?p=preview\n \n \n## Origin\n[https://damienfremont.com/2015/11/02/javaee-angularjs-bootstrap-how-to-pagination-with-smart-table/](https://damienfremont.com/2015/11/02/javaee-angularjs-bootstrap-how-to-pagination-with-smart-table/)\n \n", "dir"=>"/20151102-javaee-angularjs-bootstrap-pagination/", "name"=>"README.md", "path"=>"20151102-javaee-angularjs-bootstrap-pagination/README.md", "url"=>"/20151102-javaee-angularjs-bootstrap-pagination/"}">
        {"permalink"=>"/20151102-javaee-angularjs-bootstrap-pagination/", "layout"=>"default", "title"=>"JavaEE AngularJS Bootstrap: How to Pagination with Smart-Table", "content"=>"JavaEE AngularJS Bootstrap: How to Pagination with Smart-Table\n======\n \n![alt text](/blog/20151102-javaee-angularjs-bootstrap-pagination/screenshots/160523003531333.png)\n \n\n \nA paginated data-table with a back-end inspired by Spring-Data Repository pattern implementation and front-end using Bootstrap pagination and ng-module Smart-Table.\n\nNote: there are two famous ng-modules. Ng-Table and SmartTable. Ng-table has a lot of stars on ngmodules.org but I choose Smart-Table instead because it’s latest version is in maven repositories (183 vs 35 stars on ngmodules.org, but 2014 jar vs 2015 on mvnrepository.com).\n \n# Demo\n \n[http://localhost:8080/20151102-javaee-angularjs-bootstrap-pagination/](http://localhost:8080/20151102-javaee-angularjs-bootstrap-pagination/)\nhttp://localhost:8080/20151102-javaee-angularjs-bootstrap-pagination/\n \nA data-table with page size selector (10, 25, 50) and pagination bar (1,2,3,4,5,>,LAST)\n \n![alt text](/blog/20151102-javaee-angularjs-bootstrap-pagination/screenshots/160523003531407.png)\n \n\n \nData-table’s page size can be change to 25 or 50.\n \n![alt text](/blog/20151102-javaee-angularjs-bootstrap-pagination/screenshots/160523003531930.png)\n \n\n \nThe displayed page can be change to another (2 here).\n \n![alt text](/blog/20151102-javaee-angularjs-bootstrap-pagination/screenshots/160523003531960.png)\n \n\n \nIt’s also possible to jump to First or Last page.\n \n![alt text](/blog/20151102-javaee-angularjs-bootstrap-pagination/screenshots/160523003531986.png)\n \n\n \n# Source\n \n![alt text](/blog/20151102-javaee-angularjs-bootstrap-pagination/screenshots/160523003532015.png)\n \n\n \nDatasRepository.java\n \n```java\npackage com.damienfremont.blog;\n \nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.PageImpl;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.domain.Sort;\nimport org.springframework.data.repository.PagingAndSortingRepository;\nimport com.damienfremont.blog.ServiceJAXRS.Person;\n \npublic class DatasRepository implements PagingAndSortingRepository<Person, Serializable> {\n \n  // MOCK\n  static List<Person> datas;\n  static {\n    datas = new ArrayList<>();\n    for (int i = 0; i < 5000; i++) {\n      datas.add(new Person(i + 1, \"John\", \"Doe\"));\n      i++;\n      datas.add(new Person(i + 1, \"Mich\", \"Jogger\"));\n      i++;\n      datas.add(new Person(i + 1, \"Santa\", \"Close\"));\n    }\n  }\n \n  @Override\n  public Page<Person> findAll(Pageable arg0) {\n    int pSize = arg0.getPageSize();\n    int pNumb = arg0.getPageNumber();\n    int pFirst = pNumb * pSize;\n    int pLast = pFirst + pSize;\n    int total = datas.size();\n    List<Person> content = new ArrayList<>();\n    for (int i = 0; i < total; i++) { if (i >= pFirst && i < pLast) {\n        Person data = datas.get(i);\n        content.add(data);\n      }\n    }\n    return new PageImpl<>(content, arg0, total);\n  }\n  ...\n}\n```\n \nMyAppCONFIG.java\n \n```java\npackage com.damienfremont.blog;\n \nimport java.util.HashSet;\nimport java.util.Set;\nimport javax.ws.rs.core.Application;\n \npublic class MyAppCONFIG extends Application {\n \n  @Override\n  public Set<Class<?>> getClasses() {\n    Set<Class<?>> s = new HashSet<Class<?>>();\n    s.add(ServiceJAXRS.class);\n    return s;\n  }\n}\n```\n \nServiceJAXRS.java\n \n```java\npackage com.damienfremont.blog;\n \nimport java.io.Serializable;\nimport javax.ws.rs.GET;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.Produces;\nimport javax.ws.rs.QueryParam;\nimport javax.ws.rs.core.MediaType;\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.PageRequest;\nimport org.springframework.data.domain.Pageable;\n \n@Path(\"/person\")\npublic class ServiceJAXRS {\n \n  DatasRepository datas = new DatasRepository();\n \n  @Path(\"/page\")\n  @GET\n  @Produces(MediaType.APPLICATION_JSON)\n  public Page<Person> getAll( //\n      @QueryParam(\"sort\") String sort, //\n      @QueryParam(\"page\") Integer page, //\n      @QueryParam(\"size\") Integer size) {\n    Pageable pageRequest = new PageRequest( //\n        ((page == null) ? 0 : (page-1)), //\n        ((size == null) ? 10 : size));\n    return datas.findAll(pageRequest);\n  }\n \n  // MODEL\n  static class Person implements Serializable {\n    private static final long serialVersionUID = 9167120287441116359L;\n    public Integer id;\n    public String firstName;\n    public String lastName;\n \n    public Person() {\n \n    }\n \n    public Person(Integer id, String firstName, String lastName) {\n      super();\n      this.id = id;\n      this.firstName = firstName;\n      this.lastName = lastName;\n    }\n  }\n \n}\n```\n \nweb.xml\n \n```xml\n<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd\" version=\"3.1\">\n \n    <servlet>\n        <servlet-name>REST</servlet-name>\n        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>\n        <init-param>\n            <param-name>javax.ws.rs.Application</param-name>\n            <param-value>com.damienfremont.blog.MyAppCONFIG</param-value>\n        </init-param>\n        <init-param>\n            <param-name>jersey.config.server.provider.classnames</param-name>\n            <param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>\n        </init-param>\n        <load-on-startup>1</load-on-startup>\n    </servlet>\n    <servlet-mapping>\n        <servlet-name>REST</servlet-name>\n        <url-pattern>/api/*</url-pattern>\n    </servlet-mapping>\n \n    <servlet>\n        <servlet-name>WEBJARS</servlet-name>\n        <servlet-class>org.webjars.servlet.WebjarsServlet</servlet-class>\n        <init-param>\n            <param-name>disableCache</param-name>\n            <param-value>true</param-value>\n        </init-param>\n        <load-on-startup>2</load-on-startup>\n    </servlet>\n    <servlet-mapping>\n        <servlet-name>WEBJARS</servlet-name>\n        <url-pattern>/webjars/*</url-pattern>\n    </servlet-mapping>\n \n</web-app>\n```\n \napp.js\n \n```javascript\n'use strict';\n \nvar app = angular.module(\n  'app',\n  [ 'ngResource',\n    'smart-table'\n    ]);\n \napp.factory('Service', function($resource) {\n    return $resource('api/person/page');\n});\n \napp.controller('TableCtrl', function ($scope, Service) {\n     \n  $scope.itemsByPage = 10;\n     \n  $scope.callServer = function(tableState) {\n    $scope.isLoading = true;\n    var pagination = tableState.pagination;\n    var start = pagination.start || 0;\n    var number = pagination.number || $scope.itemsByPage;\n    Service.get({\n      page : 1+(start/number),\n      size : number\n      },\n      function(pageable) {\n        $scope.pageable = pageable;\n        $scope.items = pageable.content;\n        tableState.pagination.numberOfPages = pageable.totalPages;\n        $scope.isLoading = false;\n    });\n  };\n});\n```\n \nindex.jsp\n \n```xml\n<!DOCTYPE html>\n<html ng-app=\"app\">\n<head>\n<!-- LIBS CSS -->\n<link rel=\"stylesheet\" href=\"webjars/bootstrap/${bootstrap.version}/css/bootstrap.css\">\n<!-- LIBS JS -->\n<script src=\"webjars/angularjs/${angularjs.version}/angular.js\"></script>\n<script src=\"webjars/angularjs/${angularjs.version}/angular-resource.js\"></script>\n<script src=\"webjars/angular-smart-table/${angular-smart-table.version}/dist/smart-table.js\"></script>\n<!-- YOUR JS -->\n<script src=\"app.js\"></script>\n</head>\n<body>\n<div class=\"container\">\n<h1>Pagination</h1>\n<form ng-controller=\"TableCtrl\">\n<table class=\"table\"\n  st-table=\"items\"\n  st-pipe=\"callServer\">\n<thead>\n \n<!-- PAGE SIZE -->\n<tr>\n  <td colspan=\"3\">\n    <div class=\"btn-group pull-right ng-scope\">\n      <button type=\"button\"\n        ng-class=\"{'active':itemsByPage==10}\"\n        ng-click=\"itemsByPage=10\"\n        class=\"btn btn-default\">10</button>\n      <button type=\"button\"\n        ng-class=\"{'active':itemsByPage==25}\"\n        ng-click=\"itemsByPage=25\"\n        class=\"btn btn-default\">25</button>\n      <button type=\"button\"\n        ng-class=\"{'active':itemsByPage==50}\"\n        ng-click=\"itemsByPage=59\"\n        class=\"btn btn-default\">50</button>\n    </div>\n  </td>\n</tr>\n     \n<!-- HEADERS -->\n<tr>\n  <th>#</th>\n  <th>First Name</th>\n  <th>Last Name</th>\n</tr>\n</thead>\n \n<!-- CONTENT -->\n<tbody>\n<tr ng-repeat=\"i in items\">\n  <td>{{i.id}}</td>\n  <td>{{i.firstName}}</td>\n  <td>{{i.lastName}}</td>\n</tr>\n</tbody>\n \n<!-- PAGINATION -->\n<tfoot>\n<tr>\n  <td colspan=\"3\" class=\"text-center\">\n    <div\n      st-template=\"pagination.html\"\n      st-pagination=\"\"\n      st-items-by-page=\"itemsByPage\"></div>\n  </td>\n</tr>\n</tfoot>\n</table>\n</form>   \n</div>\n</body>\n</html>\n```\n \npagination.html\n \n```xml\n<div class=\"pagination\" ng-if=\"pages.length >= 2\">\n  <ul class=\"pagination\">\n    <li ng-if=\"currentPage > 1\">\n      <a ng-click=\"selectPage(1)\" href=\"#1\">\n        FIRST</a></li>\n    <li ng-if=\"currentPage > 1\">\n      <a ng-click=\"selectPage(currentPage-1)\" href=\"#\">\n        &lt;</a></li>\n    <li ng-repeat=\"page in pages\" ng-class=\"{active: page==currentPage}\">\n      <a ng-click=\"selectPage(page)\" href=\"\#{{page}}\">\n        {{page}}</a></li>\n    <li ng-if=\"currentPage < numPages\">\n      <a ng-click=\"selectPage(currentPage+1)\" href=\"#\">\n        &gt;</a></li>\n    <li ng-if=\"currentPage < numPages\">\n      <a ng-click=\"selectPage(numPages)\" href=\"\#{{numPages}}\">\n        LAST</a></li>\n  </ul>\n</div>\n```\n \npom.xml\n \n```xml\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n  <modelVersion>4.0.0</modelVersion>\n \n  <groupId>com.damienfremont.blog</groupId>\n  <artifactId>20151102-javaee-angularjs-bootstrap-pagination</artifactId>\n  <version>0.0.1-SNAPSHOT</version>\n  <packaging>war</packaging>\n \n  <properties>\n    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n    <!-- JAVAEE -->\n    <java.version>7</java.version>\n    <javaee.version>7.0</javaee.version>\n    <jersey.version>2.22.1</jersey.version>\n    <!-- WEB -->\n    <bootstrap.version>3.3.5</bootstrap.version>\n    <angularjs.version>1.4.7</angularjs.version>\n    <angular-ui-bootstrap.version>0.14.0</angular-ui-bootstrap.version>\n    <angular-smart-table.version>2.1.4</angular-smart-table.version>\n  </properties>\n \n  <dependencies>\n \n    <!-- JAVA -->\n \n    <dependency>\n      <groupId>javax</groupId>\n      <artifactId>javaee-api</artifactId>\n      <version>${javaee.version}</version>\n      <scope>provided</scope>\n    </dependency>\n \n    <dependency>\n      <groupId>org.glassfish.jersey.containers</groupId>\n      <artifactId>jersey-container-servlet</artifactId>\n      <version>${jersey.version}</version>\n    </dependency>\n    <dependency>\n      <groupId>org.glassfish.jersey.media</groupId>\n      <artifactId>jersey-media-json-jackson</artifactId>\n      <version>${jersey.version}</version>\n    </dependency>\n \n    <dependency>\n      <groupId>org.springframework.data</groupId>\n      <artifactId>spring-data-commons</artifactId>\n      <version>1.9.0.RELEASE</version>\n    </dependency>\n \n \n    <!-- WEB -->\n \n    <dependency>\n      <groupId>org.webjars</groupId>\n      <artifactId>webjars-servlet-2.x</artifactId>\n      <version>1.1</version>\n    </dependency>\n \n    <dependency>\n      <groupId>org.webjars</groupId>\n      <artifactId>angularjs</artifactId>\n      <version>${angularjs.version}</version>\n    </dependency>\n    <dependency>\n      <groupId>org.webjars</groupId>\n      <artifactId>angular-ui-bootstrap</artifactId>\n      <version>${angular-ui-bootstrap.version}</version>\n    </dependency>\n    <dependency>\n      <groupId>org.webjars.bower</groupId>\n      <artifactId>angular-smart-table</artifactId>\n      <version>${angular-smart-table.version}</version>\n    </dependency>\n \n    <dependency>\n      <groupId>org.webjars</groupId>\n      <artifactId>bootstrap</artifactId>\n      <version>${bootstrap.version}</version>\n    </dependency>\n \n  </dependencies>\n  <build>\n    <resources>\n      <resource>\n        <directory>src/main/webapp</directory>\n        <filtering>true</filtering>\n        <targetPath>${project.basedir}/target/m2e-wtp/web-resources</targetPath>\n        <includes>\n          <include>*.jsp</include>\n        </includes>\n      </resource>\n    </resources>\n    <plugins>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-war-plugin</artifactId>\n        <version>2.6</version>\n        <configuration>\n          <webResources>\n            <resource>\n              <directory>src/main/webapp</directory>\n              <filtering>true</filtering>\n              <includes>\n                <include>*.jsp</include>\n              </includes>\n            </resource>\n          </webResources>\n        </configuration>\n      </plugin>\n      <plugin>\n        <groupId>org.apache.maven.plugins</groupId>\n        <artifactId>maven-compiler-plugin</artifactId>\n        <version>3.1</version>\n        <configuration>\n          <source>1.${java.version}</source>\n          <target>1.${java.version}</target>\n        </configuration>\n      </plugin>\n    </plugins>\n  </build>\n</project>\n```\n \n# Project\n \n[https://github.com/DamienFremont/blog/tree/master/20151102-javaee-angularjs-bootstrap-pagination](https://github.com/DamienFremont/blog/tree/master/20151102-javaee-angularjs-bootstrap-pagination)\nhttps://github.com/DamienFremont/blog/tree/master/20151102-javaee-angularjs-bootstrap-pagination\n \n# References\n \n[http://projects.spring.io/spring-data/](http://projects.spring.io/spring-data/)\nhttp://projects.spring.io/spring-data/\n \n[http://ngmodules.org/modules/Smart-Table](http://ngmodules.org/modules/Smart-Table)\nhttp://ngmodules.org/modules/Smart-Table\n \n[http://lorenzofox3.github.io/smart-table-website/](http://lorenzofox3.github.io/smart-table-website/)\nhttp://lorenzofox3.github.io/smart-table-website/\n \n[http://plnkr.co/edit/e82rdx7R4pjbLvayUHXx?p=preview](http://plnkr.co/edit/e82rdx7R4pjbLvayUHXx?p=preview)\nhttp://plnkr.co/edit/e82rdx7R4pjbLvayUHXx?p=preview\n \n \n## Origin\n[https://damienfremont.com/2015/11/02/javaee-angularjs-bootstrap-how-to-pagination-with-smart-table/](https://damienfremont.com/2015/11/02/javaee-angularjs-bootstrap-how-to-pagination-with-smart-table/)\n \n", "dir"=>"/20151102-javaee-angularjs-bootstrap-pagination/", "name"=>"README.md", "path"=>"20151102-javaee-angularjs-bootstrap-pagination/README.md", "url"=>"/20151102-javaee-angularjs-bootstrap-pagination/"}</a></li>
    <li ng-if="currentPage < numPages">
      <a ng-click="selectPage(currentPage+1)" href="#">
        &gt;</a></li>
    <li ng-if="currentPage < numPages">
      <a ng-click="selectPage(numPages)" href="#">
        LAST</a></li>
  </ul>
</div>

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.damienfremont.blog</groupId>
  <artifactId>20151102-javaee-angularjs-bootstrap-pagination</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
 
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!-- JAVAEE -->
    <java.version>7</java.version>
    <javaee.version>7.0</javaee.version>
    <jersey.version>2.22.1</jersey.version>
    <!-- WEB -->
    <bootstrap.version>3.3.5</bootstrap.version>
    <angularjs.version>1.4.7</angularjs.version>
    <angular-ui-bootstrap.version>0.14.0</angular-ui-bootstrap.version>
    <angular-smart-table.version>2.1.4</angular-smart-table.version>
  </properties>
 
  <dependencies>
 
    <!-- JAVA -->
 
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>${javaee.version}</version>
      <scope>provided</scope>
    </dependency>
 
    <dependency>
      <groupId>org.glassfish.jersey.containers</groupId>
      <artifactId>jersey-container-servlet</artifactId>
      <version>${jersey.version}</version>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.media</groupId>
      <artifactId>jersey-media-json-jackson</artifactId>
      <version>${jersey.version}</version>
    </dependency>
 
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-commons</artifactId>
      <version>1.9.0.RELEASE</version>
    </dependency>
 
 
    <!-- WEB -->
 
    <dependency>
      <groupId>org.webjars</groupId>
      <artifactId>webjars-servlet-2.x</artifactId>
      <version>1.1</version>
    </dependency>
 
    <dependency>
      <groupId>org.webjars</groupId>
      <artifactId>angularjs</artifactId>
      <version>${angularjs.version}</version>
    </dependency>
    <dependency>
      <groupId>org.webjars</groupId>
      <artifactId>angular-ui-bootstrap</artifactId>
      <version>${angular-ui-bootstrap.version}</version>
    </dependency>
    <dependency>
      <groupId>org.webjars.bower</groupId>
      <artifactId>angular-smart-table</artifactId>
      <version>${angular-smart-table.version}</version>
    </dependency>
 
    <dependency>
      <groupId>org.webjars</groupId>
      <artifactId>bootstrap</artifactId>
      <version>${bootstrap.version}</version>
    </dependency>
 
  </dependencies>
  <build>
    <resources>
      <resource>
        <directory>src/main/webapp</directory>
        <filtering>true</filtering>
        <targetPath>${project.basedir}/target/m2e-wtp/web-resources</targetPath>
        <includes>
          <include>*.jsp</include>
        </includes>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <webResources>
            <resource>
              <directory>src/main/webapp</directory>
              <filtering>true</filtering>
              <includes>
                <include>*.jsp</include>
              </includes>
            </resource>
          </webResources>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.${java.version}</source>
          <target>1.${java.version}</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Project

https://github.com/DamienFremont/blog/tree/master/20151102-javaee-angularjs-bootstrap-pagination https://github.com/DamienFremont/blog/tree/master/20151102-javaee-angularjs-bootstrap-pagination

References

http://projects.spring.io/spring-data/ http://projects.spring.io/spring-data/

http://ngmodules.org/modules/Smart-Table http://ngmodules.org/modules/Smart-Table

http://lorenzofox3.github.io/smart-table-website/ http://lorenzofox3.github.io/smart-table-website/

http://plnkr.co/edit/e82rdx7R4pjbLvayUHXx?p=preview http://plnkr.co/edit/e82rdx7R4pjbLvayUHXx?p=preview

Origin

https://damienfremont.com/2015/11/02/javaee-angularjs-bootstrap-how-to-pagination-with-smart-table/