2014-09-05 54 views
0

我們決定在我們的應用程序中使用服務器端分頁。實現相當簡單:如何在我的應用程序中使搜索/分頁可重用?

  • 假設我們在服務器端這樣的搜索行動:

    [HttpGet] 
    public ActionResult GetPeopleByName(String term, Int32 itemsPerPage = 10, Int32 page = 0) { 
        var matches = this.people.Where(i => i.Name.Contains(term)); 
        return Json(
         data: new { 
          people = matches.Skip(itemsPerPage * page).Take(itemsPerPage).OrderBy(i => i.Name), 
          total = matches.Count() 
         }, 
         behavior: JsonRequestBehavior.AllowGet 
        ); 
    } 
    
  • 在客戶端上,我們有一個subscriptionHolderController

    app.controller('subscriptionHolderController', ['$scope', '$http', function($scope, $http) { 
        $scope.matches = []; 
        $scope.itemsPerPage = 5; 
        $scope.currentPage = 0; 
        $scope.searchTerm = ''; 
    
        // $scope.prevPage = function() { ... }; 
        // $scope.prevPageDisabled = function() { ... }; 
        // $scope.nextPage = function() { ... }; 
        // $scope.nextPageDisabled = function() { ... }; 
    
        $scope.pageCount = function() { 
         return Math.ceil($scope.totalPages/$scope.itemsPerPage); 
        }; 
    
        $scope.$watch('currentPage', function() { $scope.search(); }); 
    
        $scope.search = function() { 
         if($scope.searchTerm === '') return; 
         // initiate a GET-request with params: { page: $scope.currentPage, term: $scope.searchTerm, itemsPerPage: $scope.itemsPerPage } 
        } 
        $scope.matchesFound = function() { return $scope.matches.length > 0; } 
    }]); 
    

問題

因此我們有一個簡單的search-box。但是我們的應用程序需要另外一種類型的搜索以及一些額外的功能,它不使用搜索條件,其結果集應該按照與上面顯示的相同的方式進行分頁。

如何重新使用不同類型搜索的分頁邏輯?

+1

一個想法是將尋呼邏輯+ UI分離與分離的範圍指令。這將使您能夠在多個地方使用它。看看角度文檔中的指令部分[https://docs.angularjs.org/guide/directive]。 – CMR 2014-09-05 07:18:37

+0

你有興趣重新使用客戶端還是服務器端? – 2014-09-08 17:46:57

+0

@DaveA我想通過部分/頁面從服務器獲取數據,無論它是一個輸入(在客戶端),並且您發送一個「搜索詞」,「頁面信息」或它是一組參數綁定說'radioboxes',你發送'頁面信息'+'參數' – lexeme 2014-09-09 07:44:16

回答

4

在服務器端,您可以返回將要保存數據的通用類,即行的總數。

public class PagedResult<T> 
    { 
     public PagedResult(IEnumerable<T> data, long total) 
     { 
      Data = data; 
      Total = total; 
     } 
     public PagedResult() 
     { 
     } 
     public IEnumerable<T> Data { get; set; } 
     public long Total { get; set; } 

    } 

,你也可以抽象爲任何功能類似的輸入參數:

public class PageInfo 
    { 

     public int Page { get; set; }   
     public int PageSize { get; set; } 
     public int Skip 
     { 
      get 
      { 
       return PageSize*(Page - 1); 
      } 
     } 

     public PageInfo(int page, int pageSize) 
     { 
      Page = page; 
      PageSize = pageSize; 
     } 

    } 

和一個實際的例子可能是這樣的:

[HttpGet] 
public ActionResult GetPeopleByName(String term, PageInfo pageinfo) { 
    var matches = this.people.Where(i => i.Name.Contains(term)); 

    var pagedResult = new PagedResult<AnySearchType>{ 
      data = matches.Skip(pageinfo.skip).Take(pageinfo.size).OrderBy(i => i.Name), 
      total = matches.Count() 
     }; 

    return Json(
     data: pagedResult, 
     behavior: JsonRequestBehavior.AllowGet 
    ); 
} 

在客戶端就可以使用指令通過傳遞如下參數來抽象尋呼邏輯:

視圖

<div class="box-content" scroll-pager="pagerConfig"> 
your data 
<div> 

控制器:

你可以通過像一些配置:

$scope.pagerConfig = { 
     pageSize: 10, 
     data: 'model.Data', // some text reference to your model 
     total: 'model.Total', // some text reference to your model 
     currentPage: 1, 
     searchParamName: 'Text',// some text reference to your model 
     resource: projectResource,// pass a resource object 
     success: function (data, page, total) { 

      } 
    }; 
1

爲分頁製作單獨的類。在此類中,您可以定義用於分頁的方法,您可以將分頁應用於任何類型和不同的參數,還可以自定義應用分頁和頁面大小的字段。

0

這是我結束了:

app.directive('pager', function() { 
    return { 
     restrict: 'EA', 
     scope: { 
      onChange: '&', 
      items: '=', 
      itemsPerPage: '@' 
     }, 
     replace: true, 
     templateUrl: '/scripts/js/app/pager.html', 
     link: function(scope, el, attrs) { 
      scope.currentPage = 1; 

      scope.isFirstPage = function() { 
       return scope.currentPage === 1; 
      } 

      scope.decPage = function() { 
       if(scope.currentPage > 1) --scope.currentPage; 
      } 

      scope.isLastPage = function() { 
       return scope.currentPage >= scope.totalPages(); 
      } 

      scope.totalPages = function() { 
       return Math.ceil(scope.items.total/scope.itemsPerPage); 
      } 

      scope.incPage = function() { 
       if(!scope.isLastPage()) ++scope.currentPage; 
      } 

      scope.$watch("currentPage", function(value) { 
       scope.onChange({page: value, itemsPerPage: scope.itemsPerPage}); 
      }); 
     } 
    }; 
}); 

標記

<div id="content" ng-app="subscriptionsManager"> 
    <div ng-controller="subscriptionHolderController"> 
     <div class="row"> 
      <div class="columns medium-6 large-6"> 
       <div class="searchbar"> 
        <div class="searchbar-inner"> 
         <input ng-model="searchTerm" type="text" /> 
         <button ng-click="search(1, 35)" class="tiny">search</button> 
        </div> 
       </div> 
      <div pager items-per-page="35" items="data" on-change="respondToTheChange(page, itemsPerPage)"></div> 
      </div> 
      <div class="columns medium-6 large-6"> 
       <div class="button-group filter-sample"> 
        <button ng-click="toggleState1()" ng-class="{true: 'selected', false: 'secondary'}[state1]" class="tiny">filter1</button> 
        <button ng-click="toggleState2()" ng-class="{true: 'selected', false: 'secondary'}[state2]" class="tiny">filter2</button> 
        <button ng-click="toggleState3()" ng-class="{true: 'selected', false: 'secondary'}[state3]" class="tiny">filter3</button> 
        <button ng-click="search2(1, 35)" class="tiny">search</button> 
       </div> 
       <div pager items-per-page="35" items="data2" on-change="respondToTheChange2(page, itemsPerPage)"></div> 
      </div> 
     </div> 
    </div> 
</div>  

控制器

// search using a search term 

$scope.data = { items: [], total: 0 }; 
$scope.searchTerm = ''; 

$scope.state1 = false; 
$scope.state2 = false; 
$scope.state3 = false; 

$scope.toggleState1 = function() { 
    $scope.state1 = !$scope.state1; 
} 

$scope.toggleState2 = function() { 
    $scope.state2 = !$scope.state2; 
} 

$scope.toggleState3 = function() { 
    $scope.state3 = !$scope.state3; 
} 

$scope.search = function(page, itemsPerPage) { 
    if($scope.searchTerm === '') return; 
    if(!angular.isDefined(page) || page == null) page = 1; 
    if(!angular.isDefined(itemsPerPage) || itemsPerPage == null) itemsPerPage = 35; 

    $http({ 
     url: '/subscriptions/GetSubscribersByNamePaged', 
     method: 'GET', 
     params: { term: $scope.searchTerm, page: page, itemsPerPage: itemsPerPage } 
    }) 
    .success(function(data, status, headers, config) { 
     $scope.data = data; 
    }).error(function(data, status, headers, config) { 
     console.log('error: ' + data); 
    }); 
} 

// search using anything else 

$scope.search2 = function(page, itemsPerPage) { 
    if(!angular.isDefined(page) || page == null) page = 1; 
    if(!angular.isDefined(itemsPerPage) || itemsPerPage == null) itemsPerPage = 35; 

    $http({ 
     url: '/subscriptions/GetSubscribersByFilters', 
     method: 'GET', 
     params: { state1: $scope.state1, state2: $scope.state2, state3: $scope.state3, page: page, itemsPerPage: itemsPerPage } 
    }) 
    .success(function(data, status, headers, config) { 
     $scope.data2 = data; 
    }).error(function(data, status, headers, config) { 
     console.log('error: ' + data); 
    }); 
} 

// bind searches! 

$scope.respondToTheChange = function(page, itemsPerPage) { 
    $scope.search(page, itemsPerPage); 
} 

$scope.respondToTheChange2 = function(page, itemsPerPage) { 
    $scope.search2(page, itemsPerPage); 
} 
相關問題