6

In this plunker example I borrowd from this thread, there is an awesome example of how to create a pagination grid using AngularJs. (My question differs a bit from this similar question.)

In one of our projects, we have a quite similar solution, but in order to get some help, I will use the code from the plunker I mentioned above.

My goal: I'd like to make the pagination grid at the bottom more accessible to screen readers This is done by adding some aria-labels to the buttons of the grid, such as

aria-label="Go to first page"
aria-label="Go to previous page"
aria-label="Go to page 3"

And so on. How do I accomplish that?

Finally, here's the code:

Template:

<!DOCTYPE html>
<html ng-app="todos">

  <head>
   <link data-require="bootstrap-css@*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
    <script data-require="angular.js@*" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular.js"></script>
    <script data-require="ui-bootstrap@*" data-semver="0.12.1" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.1.min.js">    </script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-controller="TodoController">
    <h1>Todos</h1>
    <h4>{{todos.length}} total</h4>
    <ul>
      <li ng-repeat="todo in filteredTodos">{{todo.text}}</li>
    </ul>
    <pagination 
      ng-model="currentPage"
      total-items="todos.length"
      max-size="maxSize"  
      boundary-links="true">
    </pagination>
  </body>
</html>

Controller:

var todos = angular.module('todos', ['ui.bootstrap']);

todos.controller('TodoController', function($scope) {
   $scope.filteredTodos = []
  ,$scope.currentPage = 1
  ,$scope.numPerPage = 10
  ,$scope.maxSize = 5;

  $scope.makeTodos = function() {
    $scope.todos = [];
    for (i=1;i<=1000;i++) {
      $scope.todos.push({ text:'todo '+i, done:false});
    }
  };
  $scope.makeTodos(); 

  $scope.$watch('currentPage + numPerPage', function() {
    var begin = (($scope.currentPage - 1) * $scope.numPerPage)
    , end = begin + $scope.numPerPage;

    $scope.filteredTodos = $scope.todos.slice(begin, end);
  });
});
Community
  • 1
  • 1
Ilias Bennani
  • 237
  • 2
  • 11
  • 1
    hi @Ilias, you can use the uib-pagination for angular. Also add ngAria.js from https://docs.angularjs.org/api/ngAria. Then your control elements will automatically be taken care by ngAria. In this case, the screen reader will read 1,2 and so on. – Sadiksha Gautam Feb 06 '17 at 13:57

2 Answers2

3

First, let me preface by saying I've never used or looked at angular. Do you have your own copy of angular? Just poking around, the pagination element seems to be generated from a template in template/pagination/pagination.html. When I look at that source, it has stuff like

<li role="menuitem" ng-if="::directionLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-next">
   <a href ng-click="selectPage(page + 1, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle>{{::getText('next')}}
   </a>
</li>

Are you allowed to modify the templates? If so, you could add an aria-label to the <a> and even get its text the same way, from paginationConfig.

I found this by poking around ui-bootstrap-tpls-0.12.1.min.js from your plunker example.

slugolicious
  • 15,824
  • 2
  • 29
  • 43
2

Upgrade your ui-bootstrap version, if possible.

Library is right now at v2.4.0 and supports overriding pagination template since v0.14.0

After that, override default template for pagination using template-url.

template-url (Default: uib/template/pagination/pagination.html) - Override the template for the component with a custom provided template

  1. Copy default template in your code base
  2. Modify it as you wish
  3. Add template-url with file path to your <pagination> tag.

PS: Default pagination template is here; Take care to refer docs and template of the version of library you are using.

Edit: Sample from my code using template-url (ui-bootstrap v2.1.4):

<div class="text-center">
   <ul uib-pagination
     total-items="vm.totalCount"
     data-ng-if="vm.totalCount"
     ng-model="vm.page"
     items-per-page="vm.limit"
     boundary-links="true"
     max-size="3"
     template-url="app/core/components/pagination/pagination.html">
   </ul>
</div>
Sangharsh
  • 2,999
  • 2
  • 15
  • 27
  • 1
    I think this idea will work. Thank you @Sangharsh. Since the bounty will expire today, I wanted to give you points :). I will mark it correct once it works. – Sadiksha Gautam Feb 06 '17 at 08:41
  • somehow my pagination is not shown anymore. I added a template in `view/pagination.html`. And added the `template-url` in my pagination. It seems that the pagination.html is being loaded. However, the pagination is not visible anymore. This is what I have now for pagination: `` – Sadiksha Gautam Feb 06 '17 at 12:20
  • `uib-pagination` directive is restricted to attributes (`restrict: 'A'`). Please use it with some tag e.g. `
      `.
    – Sangharsh Feb 06 '17 at 12:33
  • Any errors on browser console? Also, which version of UI Bootstrap are you using? – Sangharsh Feb 06 '17 at 12:48
  • there is no error on the browser console. I am using bootstrap version Version: 1.3.2 – Sadiksha Gautam Feb 06 '17 at 13:43
  • 1
    Glad I could get the ball rolling and contribute the initial idea as well as find the template that needs to be modified and the change required. – slugolicious Feb 07 '17 at 14:49