如何处理Knockout的分页 [英] How to handle pagination with Knockout
问题描述
我有一个设置为绑定到 observeableArray
的div,但我只想显示来自 observeableArray的最多50个项目
在任何给定时间。我想通过页面上的上一个和下一个按钮以及索引来处理这个问题,以允许用户循环浏览集合中的项目页面。
我知道我可以用 computedObservable
和一个自定义数据绑定,但我不知道该怎么做(我仍然是一个淘汰赛新手)。
谁能指出我正确的方向?
I have a div that is setup to bind to a observeableArray
,but I only want to show at most 50 items from that observeableArray
at any given time. I want to handle this with pagination with a previous and next button along with indices on the page to allow users to cycle through pages of items from the collection.
I know I could probably do this with a computedObservable
and a custom data binding but I'm not sure how to do it (I'm still a Knockout neophyte).
Can anyone point me in the right direction?
这是我的代码(JS在TypeScript中):
Here is my code (the JS is in TypeScript):
<div class="container-fluid">
<div class="row-fluid">
<div class="span12">
<%=
if params[:q]
render 'active_search.html.erb'
else
render 'passive_search.html.erb'
end
%>
<%= form_tag("/search", method: "get", :class => "form-search form-inline") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q, nil, class:"input-medium search-query") %>
<%= submit_tag("Search", :class=>"btn") %>
<% end %>
<div class="media" data-bind="foreach: tweetsArray">
<%= image_tag('twitter-icon.svg', :class=>"tweet_img", :style=>"display:inline;") %>
<div class="media-body" style="display:inline;">
<h4 class="media-heading" data-bind="text: user.screen_name" style="display:inline;"></h4>
<span data-bind="text:text" style="display:inline;"></span> <br />
<span data-bind="text:'Created at '+created_at"></span> <br />
</div>
</div>
<div class="pagination pagination-centered">
<ul>
<li>
<a href="#">Prev</a>
</li>
<li>
<a href="#">1</a>
</li>
<li>
<a href="#">Next</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<script>
var viewModel = new twitterResearch.TweetViewModel();
ko.applyBindings(viewModel);
//TODO: notes to self, use custom binding for pagination along with a computed observable to determine where at in the list you are
//document.onReady callback function
$(function() {
$.getJSON('twitter', {}, function(data) {
viewModel.pushTweet(data);
console.log(data.user);
});
});
</script>
declare var $: any;
declare var ko: any;
module twitterResearch {
class Tweet {
text: string;
created_at: string;
coordinates: string;
user: string;
entities: string;
id: number;
id_str: string;
constructor(_text: string, _created_at: string, _coordinates: any, _user: any,
_entities: any, _id_str: string, _id: number){
this.text = _text;
this.created_at = _created_at;
this.coordinates = _coordinates;
this.user = _user;
this.entities = _entities;
this.id_str = _id_str;
this.id = _id;
}
}
export class TweetViewModel{
tweetsArray: any;
constructor()
{
this.tweetsArray = ko.observableArray([]);
}
//tweet is going to be the JSON tweet we return
//from the server
pushTweet(tweet)
{
var _tweet = new Tweet(tweet.text, tweet.created_at, tweet.coordinates,
tweet.user, tweet.entities, tweet.id_str, tweet.id);
this.tweetsArray.push(_tweet);
this.tweetsArray.valueHasMutated();
}
}
}
推荐答案
使用Knockout进行分页非常简单。我个人会这样做:
Pagination is quite simple with Knockout. I would personally achieve it this way:
- 有一个包含所有元素的observableArray
- 有一个包含当前页面的observable(初始化为0)
- 有一个变量声明每页元素的数量
- 有一个计算结果返回的数字页面,由于每页元素的数量和元素的总数而计算。
- 最后,添加一个计算切片包含所有元素的数组。
- Have an observableArray containing all your elements
- Have an observable containing the current page (initialized to 0)
- Have a variable declaring the number of elements per page
- Have a computed that returns the number of pages, calculated thanks to the number of elements per page and the total number of elements.
- Finally, add a computed that slices the array containing all the elements.
鉴于此,您现在可以添加一个递增(下一个)或递减(前一个)当前页面的函数。
Given that, you can now add a function that increments (next) or decrements (previous) the current page.
这是一个简单的例子:
var Model = function() {
var self = this;
this.all = ko.observableArray([]);
this.pageNumber = ko.observable(0);
this.nbPerPage = 25;
this.totalPages = ko.computed(function() {
var div = Math.floor(self.all().length / self.nbPerPage);
div += self.all().length % self.nbPerPage > 0 ? 1 : 0;
return div - 1;
});
this.paginated = ko.computed(function() {
var first = self.pageNumber() * self.nbPerPage;
return self.all.slice(first, first + self.nbPerPage);
});
this.hasPrevious = ko.computed(function() {
return self.pageNumber() !== 0;
});
this.hasNext = ko.computed(function() {
return self.pageNumber() !== self.totalPages();
});
this.next = function() {
if(self.pageNumber() < self.totalPages()) {
self.pageNumber(self.pageNumber() + 1);
}
}
this.previous = function() {
if(self.pageNumber() != 0) {
self.pageNumber(self.pageNumber() - 1);
}
}
}
你会发现一个简单的这里有完整的例子: http://jsfiddle.net/LAbCv/ (可能有点儿马车,但是想法就在那里。
You'll find a simple and complete example here: http://jsfiddle.net/LAbCv/ (might be a bit buggy, but the idea is there).
这篇关于如何处理Knockout的分页的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!