1

I'm using the angular-ui:bootstrap pagination directive on multiple views which interact with different controllers; these views/controllers often have to interact with sorting and filtering, which need to update the page size dynamically, eg:

              <pagination 
                on-select-page="setPage(page)" 
                items-per-page="pageSize" 
                boundary-links="true" 
                total-items="totalItems" 
                page="search.page" 
                max-size="maxVisiblePages" 
                class="pagination-sm"
                num-pages="numPages"
                previous-text="&lsaquo;" 
                next-text="&rsaquo;" 
                first-text="&laquo;" 
                last-text="&raquo;" 
                >
              </pagination>

In each of my controllers, I must re-define these $scope functions, eg:

      $scope.setPage = (page) ->
        $timeout ->
          $scope.search.page = page if $scope.search.page isnt page
          $scope.totalItems = $scope.matchedItems.length
          startIndex = (page - 1) * $scope.pageSize
          $scope.images = $scope.matchedItems.slice(startIndex, startIndex + $scope.pageSize)
          return
      $scope.sortMatches = ->
        $scope.matchedItems= $filter("orderBy")($scope.matchedItems, ['type','name'], true)
        $scope.setPage 1
        return
       ...

What is the best way to give me this sorting/filtering/pagination functionality while avoiding code repetition in both the controllers and the view? I was thinking that I could create a class which installs the $scope functions and another directive which wraps the <pagination> directive but I don't know if this is the best option.

Blaskovicz
  • 6,122
  • 7
  • 41
  • 50

1 Answers1

0

The general rule with Angular is that if you need to share code it's either a service or a factory. For your case I'd go with a service. For instance, I have a "cancel" service that I use in several controllers:

  module.service "cancelService", ($location) ->
    @cancel = ->
      if (/#/.test($location.$$path))
        $location.path($location.$$path.replace(/#.*/, "##{moment()}"))
      else
        $location.path($location.$$path += "#" + moment());
    @

  module.controller('adminUserEdit', ["$scope", '$route',"$location", '$stateParams', "userService",'roleService', 'cancelService', ($scope, $route, $location, $stateParams, userService, roleService, cancelService) -> 
    $scope.cancel = cancelService.cancel

That way I have one line that pulls the cancelService function into any controller that needs to cancel things.

jcollum
  • 43,623
  • 55
  • 191
  • 321
  • So are you suggesting that I inject the $scope into a service and add use that to define the common functions? – Blaskovicz May 08 '14 at 18:13
  • No I think it'd be the other way around. Keep the common code in the service, then attach pointers to those functions in your controller code. Related: http://stackoverflow.com/questions/15509457/passing-current-scope-to-an-angularjs-service – jcollum May 09 '14 at 20:31