2017-04-04 1 views
0

녹아웃 구성 요소 수준에서 페이지 매김을 처리하는 현재 및 미래 프로젝트의 구성 요소를 작성하고 있습니다. 나는 대답을 here에서 받아 들였습니다. 또한 녹아웃 구성 요소 페이지 here을 참조하십시오.knockout.js 구성 요소를 사용하여 페이지 매김을 올바르게 작성하는 방법은 무엇입니까?

여기까지 내 구성 요소입니다. 동적 테이블 표제는 물론 실제로 표시 할 데이터를 얻는 데 문제가 있습니다.

ko.components.register("jPage", { 
viewModel: function (params) { 
    var self = this; 
    self.Items = params.Items; 
    self.Keys = Object.keys(self.Items); 
    self.PerPage = params.PerPage; 
    self.Page = 1; 
    self.PagesTotal = Math.ceil(self.Items.length/self.PerPage); 

    self.ItemsVisible = ko.computed(function() { 
     first = (self.Page * self.PerPage) - self.PerPage; 
     return self.Items.slice(first, first + self.PerPage); 
    }) 

    self.ChangePage = function (_page) { 
     if (_page < 1 || _page > self.PagesTotal) return; 
     this.Page(_page); 
    }.bind(this); 


}, 
template: 
    '<div data-bind="foreach: ItemsVisible"> \ 
     Display Table headers and data here <br>\ 
     <span data-bind="text: $data[0]"> </span>\ 
    </div>\ 
    <nav aria-label="Page navigation">\ 
    <ul class="pagination">\ 
     <li data-bind="css:{disabled: Page <= 1} ">\ 
      <a aria-label="Previous" data-bind="click: ChangePage(Page - 1)">\ 
       <span aria-hidden="true">&laquo;</span>\ 
      </a>\ 
     </li>\ 
     <li><a data-bind="text: Page -2, click: ChangePage(Page - 2), visible: Page > 2 "> </a></li>\ 
     <li><a data-bind="text: Page -1, click: ChangePage(Page - 1), visible: Page > 1 "> </a></li>\ 
     <li class="active"><a data-bind="text: Page"> </a></li>\ 
     <li><a data-bind="text: Page +1, click: ChangePage(Page + 1), visible: (PagesTotal > Page +0) "></a></li>\ 
     <li><a data-bind="text: Page +2, click: ChangePage(Page + 2), visible: (PagesTotal > Page +1)"></a></li>\ 
     <li data-bind="css: {disabled: (PagesTotal < Page)}">\ 
      <a aria-label="Next" data-bind="click: ChangePage(Page + 1)">\ 
       <span aria-hidden="true">&raquo;</span>\ 
      </a>\ 
     </li>\ 
    </ul>\ 
</nav>\ 
' 
}) 

이 구성 요소를 호출 할 것이다 방법입니다

[ 
    {FirstName: "John", Email: "[email protected]"}, 
    {FirstName: "Steve", Email: "[email protected]"}, 
    {FirstName: "Jim", Email: "[email protected]"} 
] 

어떤 변수 나 상황에 맞는 것은 내가 Items 키/값에 액세스 할 수없는 오전 :

<div data-bind="component: { name: 'jPage', params: { Items: CustomerList(), PerPage: 25} }"> 

CustomerList과 같을 것이다?

추가 참고 사항. 결과없이 조작 할 수 있기 때문에 필요한 데이터 형식이 없습니다.

+0

첫째는 속성을 관찰해야 변화에 반응합니다. 그래서 페이지 속성은 그다지 효과가 없을 것입니다. 일단 그것을 고치고 사용 된 모든 참조를 삭제하면 많은 문제가 사라집니다. http://knockoutjs.com/documentation/observables.html –

답변

2

좋아. 이것을 알아 내기까지 6 개월이 걸렸습니다. 그러나 희망을 갖고 다른 누군가는 내가 가지고있는 것만 큼 이것을 귀중한 것으로 생각할 것입니다.

내가 발견 한 트릭은 구성 요소를 사용하는 것이 아니라 HTML 전용 템플릿입니다. 비록 내가 구성 요소가 작동 할지도 모르겠지만.

다음은 페이지 매김을위한 뷰 모델 코드와 그 작동 방식에 대한 간단한 예입니다. 그것은 오직 하나의 입력과 배열을 필요로합니다. 그리고 나서 PerPage을 묶고 출력을 PaginatedArray, tah dah로 묶으십시오. 순서

function MainViewModel() { 
 
    var self = this; 
 

 
    self.ListOfStuff = ko.observableArray(); 
 

 
    self.Pagination = ko.observable(new PaginationVM(self.ListOfStuff)); 
 

 
    self.PopulateArray = function() { 
 
    for (var i = 0; i < 100; i++) { 
 
     self.ListOfStuff.push("Item " + i); 
 
    } 
 
    } 
 
    self.PopulateArray(); 
 
} 
 

 

 
function PaginationVM(input) { 
 
    var self = this; 
 
    self.InputArray = input; 
 
    self.PerPage = ko.observable(); 
 
    self.Page = ko.observable(1); 
 

 
    self.PageTotal = ko.computed(function() { 
 
    var totalPages = Math.ceil(self.InputArray().length/parseInt(self.PerPage())); 
 
    if (self.Page() > totalPages && totalPages > 0) { 
 
     self.Page(totalPages); 
 
    } 
 
    return totalPages 
 
    }) 
 

 
    self.PaginatedArray = ko.computed(function() { 
 
    var perPage = parseInt(self.PerPage()) 
 
    var start = self.Page() * perPage - perPage; 
 
    return self.InputArray().slice(start, start + perPage); 
 
    }) 
 

 
    self.ChangePageBy = function(offset) { 
 
    return function() { 
 
     self.Page(self.Page() + offset); 
 
    } 
 
    } 
 

 
    self.ChangePageTo = function(newPage) { 
 
    return function() { 
 
     switch (newPage) { 
 
     case "last": 
 
      self.Page(self.PageTotal()); 
 
      break; 
 
     case "first": 
 
      self.Page(1); 
 
      break; 
 
     default: 
 
      self.Page(newPage); 
 
     } 
 
    } 
 
    } 
 
} 
 

 

 
ko.applyBindings(new MainViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 
 

 
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> 
 

 
<!-- This is the template needed for the view model but you can style it as necessary 
 
Its bootstrap right now.--> 
 
<script type="text/html" id="PaginationTemplate"> 
 
    <nav class="text-center" aria-label="Page navigation"> 
 
    <ul class="pagination" style="cursor:pointer"> 
 
     <li data-bind="css:{disabled: Page() <= 1} "> 
 
     <a aria-label="Previous" data-bind="click: ChangePageTo('first')"> 
 
      <span aria-hidden="true">&laquo;</span> 
 
     </a> 
 
     </li> 
 
     <li> 
 
     <a data-bind="text: Page() -2, click: ChangePageBy(-2), visible: Page() > 2 "> </a> 
 
     </li> 
 
     <li> 
 
     <a data-bind="text: Page() -1, click: ChangePageBy(-1), visible: Page() > 1 "> </a> 
 
     </li> 
 
     <li class="active"> 
 
     <a data-bind="text: Page() "> </a> 
 
     </li> 
 
     <li> 
 
     <a data-bind="text: Page() +1, click: ChangePageBy(1), visible: (PageTotal() > Page() +0)"></a> 
 
     </li> 
 
     <li> 
 
     <a data-bind="text: Page() +2, click: ChangePageBy(2), visible: (PageTotal() > Page() +1)"></a> 
 
     </li> 
 

 
     <li data-bind="css: {disabled: (PageTotal() < Page() +1)}"> 
 
     <a aria-label="Next" data-bind="click: ChangePageTo('last')"> 
 
      <span aria-hidden="true">&raquo;</span> 
 
     </a> 
 
     </li> 
 
    </ul> 
 
    </nav> 
 
</script> 
 

 

 
<!-- This is what it looks like without pagination. 
 
<div data-bind="foreach: ListOfStuff"> 
 
    <span data-bind="text: $data"> </span><br> 
 
</div>--> 
 
<select data-bind="value: Pagination().PerPage"> 
 
           <option value="10">10</option> 
 
           <option value="25">25</option> 
 
           <option value="50">50</option> 
 
           <option value="100">100</option> 
 
          </select> 
 
<div data-bind="foreach: Pagination().PaginatedArray"> 
 
    <span data-bind="text: $data"></span><br> 
 
</div> 
 
<div data-bind="template: { name : 'PaginationTemplate', data: Pagination }">