var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, $filter) {
  $scope.name = 'World';
  $scope.availableItemsLeft = [];
  $scope.availableItemsRight = [];
  
  for (var i = 0; i < 25; i++) {
    $scope.availableItemsLeft.push({ name: 'name' + i, id: 'id' + i });
    //$scope.availableItemsRight.push({ name: 'name0' + i, id: 'id0' + i });
  }

});

app.filter('startFrom', function() {
  return function(input, start) {
    start = +start;
    return input.slice(start);
  };
});
<!DOCTYPE html>
<html ng-app="plunker">

<head>
  <meta charset="utf-8" />
  <title>AngularJS Plunker</title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.20/angular.js" data-semver="1.3.20"></script>
  <script src="app.js"></script>
  <script src="myPageableMultiSelect.js"></script>
  <script src="mySearchableMultiSelectComponent.js"></script>
</head>

<body ng-controller="MainCtrl">
  <p>Hello {{name}}!</p>
  <div style='height: 300px;'>
    <my-searchable-multi-select-component
      my-left-data='availableItemsLeft'
      my-right-data='availableItemsRight'
      my-page-size='4'
      my-left-choice-name='Available'
      my-right-choice-name='Selected'
      my-left-section-name='Available Items'
      my-right-section-name='Selected Items'
    ></my-searchable-multi-select-component>
  </div>
  <div style='width: 100%'>
  <hr/>
  Items in Right list (selected items): <br/> {{availableItemsRight}}
  </div>
  <hr/><hr/>
  <p>Hello {{name}}!</p>
  <div style='height: 300px;'>
    <my-searchable-multi-select-component
      my-left-data='availableItemsLeft'
      my-right-data='availableItemsRight'
      my-page-size='10'
      disable-pagination='true'
      disable-search='true'
      my-left-choice-name='Available'
      my-right-choice-name='Selected'
      my-left-section-name='Available Items'
      my-right-section-name='Selected Items'
    ></my-searchable-multi-select-component>
  </div>
  <div style='width: 100%'>
  <hr/>
  Items in Right list (selected items): <br/> {{availableItemsRight}}
  </div>
</body>

</html>
/* Put your css in here */

button {
  margin: 5px;
}

button[disabled=disabled] {
  opacity: 0.5;
  cursor: not-allowed; /*not sure why not working*/
}
<div>
  
  <select multiple
    ng-options='item as item.name for item in myData | filter: (mySearchCondition == "true" ? mySearchString : "") | startFrom: pagination.page * pagination.perPage | limitTo: pagination.perPage'
    ng-model='mySelectedItems' 
    ng-attr-size='{{myPageSize}}' 
    ></select>

  <div ng-if='!hidePagination'>
    <button ng-disabled='pagination.page == 0' ng-click='gotoFirst()'>&lt;&lt;</button>
    <button ng-disabled='pagination.page == 0' ng-click='gotoPrev()'>&lt;</button>
    <button ng-disabled='pagination.page + 1 > pagination.numPages' ng-click='gotoNext()'>&gt;</button>
    <button ng-disabled='pagination.page + 1 > pagination.numPages' ng-click='gotoLast()'>&gt;&gt;</button>
  </div>

</div>
app.directive('myPageableMultiSelect', ['$filter', function($filter) {
  return {
    restrict: 'AE',
    scope: {
      myData: '=myAvailableOptions',
      mySelectedItems: '=mySelectedOptions',
      myPageSize: '@',
      mySectionName: '@',
      mySearchCondition: '@',
      mySearchString: '@',
      disablePagination: '@'
    },
    link: function(scope, el, attr) {
      el.find('select').css('width', '200px');
      
      var refreshPagination;
      if (attr.disablePagination == 'true') {
        scope.hidePagination = true;
        
        refreshPagination = function () {
          scope.pagination = {
            page: 0,
            perPage: scope.myData.length,
            numPages: 1
          };
          if (scope.myData.length % scope.myPageSize === 0) {
            scope.pagination.numPages--;
          }
        };
        scope.pagination = {
          page: 0,
          perPage: scope.myData.length,
          numPages: 1
        };
        
      } else {
        scope.hidePagination = false;

        refreshPagination = function () {
          var displayingData = $filter('filter')(scope.myData, scope.mySearchString);
          scope.pagination = {
            page: 0,
            perPage: scope.myPageSize,
            numPages: parseInt(displayingData.length / scope.myPageSize)
          };
          if (scope.myData.length % scope.myPageSize === 0) {
            scope.pagination.numPages--;
          }
        };
        scope.gotoFirst = function() {
          scope.pagination.page = 0;
        };
        scope.gotoLast = function() {
          scope.pagination.page = scope.pagination.numPages;
        };
        scope.gotoPrev = function() {
          if (scope.pagination.page > 0) {
            scope.pagination.page -= 1;
          }
        };
        scope.gotoNext = function() {
          if (scope.pagination.page <= scope.pagination.numPages - 1) {
            scope.pagination.page += 1;
          }
        };
        
        refreshPagination();
      }
      scope.$watchCollection('myData', function() {
        refreshPagination();
      });
      scope.$watch('mySearchString', function() {
        refreshPagination();
      });
    },
    controller: ['$scope', function($scope) {
    }],
    templateUrl: 'my-pageable-multi-select.html'
  };
}]);
<div>
  <div ng-if='!hideSeachSection'>
    Search: <input ng-model='search.tempSearchStr'/>
    
    <br/>
    From: 
    <input type='radio' value='all' ng-model='search.tempSelection' />All
    <input type='radio' value='left' ng-model='search.tempSelection' />{{myLeftChoiceName}}
    <input type='radio' value='right' ng-model='search.tempSelection' />{{myRightChoiceName}}
    <input type='button' value='Search' ng-click='applySearch()' />
  </div>
  <br/>
  
  <div style='width: 500px'>
    <div style='width: 44%; float: left'>
      {{myLeftChoiceName}}
      <my-pageable-multi-select 
        my-available-options='availableItemsLeft' 
        my-selected-options='selectedItemsLeft' 
        my-page-size='{{myPageSize}}' 
        my-section-name='{{myLeftSectionName}}'
        my-search-string='{{search.searchStr}}'
        my-search-condition='{{search.selection != "right"}}'
        disable-pagination='{{disablePagination}}'
        ></my-pageable-multi-select>
    </div>
    <div style='width:10%; margin-top: 30px; float: left;'>
      <button ng-disabled='availableItemsRight.length == 0' ng-click='addAllItemsToLeft()'>&lt;&lt;</button>
      <br/>
      <button ng-disabled='selectedItemsRight.length == 0' ng-click='addItemToLeft()'>&lt;</button>
      <br/>
      <button ng-disabled='selectedItemsLeft.length == 0' ng-click='addItemToRight()'>&gt;</button>
      <br/>
      <button ng-disabled='availableItemsLeft.length == 0' ng-click='addAllItemsToRight()'>&gt;&gt;</button>
    </div>
    <div style='width: 45%; float: left'>
      {{myRightChoiceName}}
      <my-pageable-multi-select 
        my-available-options='availableItemsRight' 
        my-selected-options='selectedItemsRight' 
        my-page-size='{{myPageSize}}' 
        my-section-name='{{myRightSectionName}}'
        my-search-string='{{search.searchStr}}'
        my-search-condition='{{search.selection != "left"}}'
        disable-pagination='{{disablePagination}}'
        ></my-pageable-multi-select>
    </div>
  </div>
</div>
app.directive('mySearchableMultiSelectComponent', function() {
  return {
    restrict: 'AE',
    scope: {
      myLeftData: '=',
      myRightData: '=',
      myPageSize: '@',
      myRightChoiceName: '@',
      myLeftChoiceName: '@',
      myRightSectionName: '@',
      myLeftSectionName: '@',
      disablePagination: '@',
      disableSearch: '@'
    },
    templateUrl: 'my-searchable-multi-select-component.html',
    controller: ['$scope', '$filter', function($scope, $filter) {

      $scope.availableItemsLeft = $scope.myLeftData;
      $scope.availableItemsRight = $scope.myRightData;
      $scope.selectedItemsLeft = [];
      $scope.selectedItemsRight = [];
      
      $scope.search = {};
      $scope.search.tempSearchStr = '';
      $scope.search.tempSelection = 'all';
      $scope.hideSeachSection =
        ($scope.disableSearch && $scope.disableSearch === 'true') ? true : false;
      
      $scope.search.searchStr = '';
      $scope.search.selection = 'all';
      
      $scope.applySearch = function(){
        $scope.search.searchStr = $scope.search.tempSearchStr;
        $scope.search.selection = $scope.search.tempSelection;
      };

      $scope.addAllItemsToLeft = function() {
        angular.forEach($scope.availableItemsRight, function(availableItem, key) {
          $scope.availableItemsLeft.push(availableItem);
        });
        $scope.selectedItemsRight.splice(0, $scope.selectedItemsRight.length);
        $scope.availableItemsRight.splice(0, $scope.availableItemsRight.length);
      };

      $scope.addAllItemsToRight = function() {
        angular.forEach($scope.availableItemsLeft, function(availableItem, key) {
          $scope.availableItemsRight.push(availableItem);
        });
        //$scope.selectedItemsLeft.splice(0, $scope.selectedItemsLeft.length);
        //$scope.availableItemsLeft.splice(0, $scope.availableItemsLeft.length);
        $scope.selectedItemsLeft = [];
        $scope.availableItemsLeft = [];
      };

      $scope.addItemToRight = function() {
        angular.forEach($scope.selectedItemsLeft, function(selectedItem, key) {
          $scope.availableItemsRight.push(selectedItem);
          angular.forEach($scope.availableItemsLeft, function(availableItem, index) {
            if (availableItem === selectedItem) {
              $scope.availableItemsLeft.splice(index, 1);
            }
          });
        });

        $scope.selectedItemsLeft.splice(0, $scope.selectedItemsLeft.length);
      };

      $scope.addItemToLeft = function() {
        angular.forEach($scope.selectedItemsRight, function(selectedItem, key) {
          $scope.availableItemsLeft.push(selectedItem);
          angular.forEach($scope.availableItemsRight, function(availableItem, index) {
            if (availableItem === selectedItem) {
              $scope.availableItemsRight.splice(index, 1);
            }
          });
        });

        $scope.selectedItemsRight.splice(0, $scope.selectedItemsRight.length);
      };

    }]
  };
});