【发布时间】:2015-06-07 20:30:04
【问题描述】:
我正在编写一个分页表,底部有一个页面选择器,显示不同的页码
我正在使用淘汰赛。这些数字来自 ko.computed 数组 (self.pages),该数组根据每页的结果/结果数计算有多少页。我遇到的问题是如果数据数组很长并且每页的结果设置得有点低,我会得到这样的结果:
我想要做的是将菜单项的数量限制为三个,因此如果选择了第 4 页,则只有项目 3、4、5 可见。目前我正在实现第二个 ko.computed,它首先检索 self.pages 的值,然后获取当前页码 (self.pageNumber) 的值,然后对数组进行切片以便只返回 3 个项目:
self.availablePages = ko.computed(function() {
var pages = self.pages();
var current = self.pageNumber();
if (current === 0) {
return pages.slice(current, current + 3);
} else {
return pages.slice(current - 1, current + 2);
}
});
现在所有这一切似乎都运行良好,但有一个错误我无法消除。使用敲除 css 数据绑定,我告诉它为任何与 self.pageNumber 具有相同值的元素分配一个 'selected' 类(参见下面的代码)。
如果选择的元素不需要self.availablePages改变(即选择2,而1是之前的选择),没有问题; 2 变为选中状态,1 变为未选中状态。
但是,如果选择确实需要 self.availablePages 更改(即 1,2,3 可见,选择 3 将更改为可见 2,3,4),则显示正确的数字,但不是选择 3,而是选择 4被选中。我假设这是因为 3 曾经位于(最后)的数组的索引现在被 4 占用了。
这是菜单:
<ul data-bind="foreach: availablePages">
<li data-bind="if: $index() < 1">
<a data-bind="click: $parent.toFirstPage">First</a>
</li>
<li>
<a data-bind="text: displayValue, click: $parent.goToPage(iterator), css: { selected: $parent.pageNumber() === iterator }"></a>
</li>
<li data-bind="if: $parent.isLastIteration($index)">
<a data-bind="click: $parent.toLastPage">Last</a>
</li>
</ul>
被迭代的数组最初只是一个数字数组,但在尝试修复这个错误时,我将其更改为以下对象的数组:
available.MenuModel = function(iterator) {
var self = this;
self.displayValue = iterator + 1;
self.iterator = iterator;
self.isSelected = ko.observable(false);
}
我尝试做的一件事是将self.isSelected observable 添加到菜单中的所有项目,然后当self.availablePages 被重新计算时,该函数检查 pageNumber 是什么,然后找到数组中的哪个项目匹配并设置self.isSelected(true),然后尝试将css绑定键控到那个。
不幸的是,这不起作用;它仍然有完全相同的错误。我一直在疯狂地调试脚本,似乎没有问题;一切似乎都知道应该选择 3,但实际选择的是 4。
我猜淘汰赛绑定不够聪明,无法跟上这一点。有什么我可以做的或一些有助于淘汰赛跟踪应该选择哪个元素的模式吗?我什至尝试将其完全淘汰,并在脚本中手动删除/添加'selected'类,只要self.pageNumber 更改和/或self.availablePages 更改但我仍然遇到了同样的问题,所以也许这不是淘汰赛问题,而是 javascript 的问题。
我已经尝试了我能想到的所有其他方法;订阅各种 observables、promise,但就像我说的那样,一切都已经知道应该选择什么,因此额外的检查和回调不会改变任何东西,也不会消除错误。
我希望有人会知道错误的原因/解决方案,或者知道更聪明的方法来完成任务。这是self.availablePages 关闭的self.pages,以防万一:
self.pages = ko.computed(function() {
var start = self.totalPages();
var pages = [];
for (var i = 0; i < start + 1; ++i)
pages.push(new available.MenuModel(i));
return pages;
});
这是整个 javascript 模型(使用 requireJs):
define(['underscore', 'knockout'], function(_, ko) {
var available = available || {};
available.DynamicResponsiveModel = function(isDataObservable, isPaginated) {
var self = this;
self.workingArray = ko.observableArray([]);
self.backgroundArray = ko.observableArray([]);
self.pageNumber = ko.observable(0);
self.count = function () {
return 15;
}
self.resultsPerPage = ko.observable(self.count());
self.selectResultsPerPage = [25, 50, 100, 200, 500];
self.resultsPerPageOptions = ko.computed(function () {
return self.selectResultsPerPage;
});
self.activeSortFunction = isDataObservable ? available.sortAlphaNumericObservable : available.sortAlphaNumeric;
self.resetPageNumber = function() {
self.pageNumber(0);
}
self.initialize = function(data) {
var sortedList = data.sort(function(obj1, obj2) {
return obj2.NumberOfServices - obj1.NumberOfServices;
});
self.workingArray(sortedList);
self.backgroundArray(sortedList);
self.pageNumber(0);
}
self.intializeWithoutSort = function(data) {
self.workingArray(data);
self.backgroundArray(data);
self.pageNumber(0);
}
self.totalPages = ko.computed(function() {
var num = Math.floor(self.workingArray().length / self.resultsPerPage());
num += self.workingArray().length % self.resultsPerPage() > 0 ? 1 : 0;
return num - 1;
});
self.paginated = ko.computed(function () {
if (isPaginated) {
var first = self.pageNumber() * self.resultsPerPage();
return self.workingArray.slice(first, first + self.resultsPerPage());
} else {
return self.workingArray();
}
});
self.pages = ko.computed(function() {
var start = self.totalPages();
var pages = [];
for (var i = 0; i < start + 1; ++i)
pages.push(new available.MenuModel(i));
return pages;
});
self.availablePages = ko.computed(function() {
var pages = self.pages();
var current = self.pageNumber();
if (current === 0) {
return pages.slice(current, current + 3);
} else {
return pages.slice(current - 1, current + 2);
}
});
self.pageNumDisplay = ko.computed(function() {
return self.pageNumber() + 1;
});
self.hasPrevious = ko.computed(function() {
return self.pageNumber() !== 0;
});
self.hasNext = ko.computed(function() {
return self.pageNumber() !== self.totalPages();
});
self.next = function() {
if (self.pageNumber() < self.totalPages()) {
self.pageNumber(self.pageNumber() + 1);
}
}
self.previous = function() {
if (self.pageNumber() != 0) {
self.pageNumber(self.pageNumber() - 1);
}
}
self.toFirstPage = function() {
self.pageNumber(0);
}
self.toLastPage = function() {
self.pageNumber(self.totalPages());
}
self.setPage = function(data) {
return new Promise(function(resolve, reject) {
self.pageNumber(data);
});
}
self.goToPage = function(data) {
self.pageNumber(data);
}
self.isLastIteration = function (index) {
var currentIndex = index();
var count = self.pages().length;
return currentIndex === count - 1;
}
self.resultsPerPage.subscribe(function() {
self.pageNumber(0);
});
self.filterResults = function (filterFunction) {
self.resetPageNumber();
self.workingArray(filterFunction(self.backgroundArray()));
}
self.resetDisplayData = function() {
self.workingArray(self.backgroundArray());
}
self.updateVisibleResults = function(data) {
self.workingArray(data);
}
}
available.sortAlphaNumericObservable = function () {
//...
}
available.sortAlphaNumeric = function () {
//...
}
return available;
});
这是整个表格:
<div data-bind="visible: showListOfEquipment, with: availableEquipmentModel">
<section class="panel panel-default table-dynamic">
<table class="primary-table table-bordered">
<thead>
<tr>
<th>
<div class="th">
Part Number
<span class="fa fa-angle-up" data-bind="click: function () { sortByFirstColumn(false); }"></span>
<span class="fa fa-angle-down" data-bind="click: function () { sortByFirstColumn(true); }"></span>
</div>
</th>
<th>
<div class="th">
Serial Number
<span class="fa fa-angle-up" data-bind="click: function () { sortBySecondColumn(false); }"></span>
<span class="fa fa-angle-down" data-bind="click: function () { sortBySecondColumn(true); }"></span>
</div>
</th>
<th>
<div class="th">
Type
<span class="fa fa-angle-up" data-bind="click: function () { sortByThirdColumn(false); }"></span>
<span class="fa fa-angle-down" data-bind="click: function () { sortByThirdColumn(true); }"></span>
</div>
</th>
<th>
<div class="th">
Equipment Group
<span class="fa fa-angle-up" data-bind="click: function () { sortByFourthColumn(false); }"></span>
<span class="fa fa-angle-down" data-bind="click: function () { sortByFourthColumn(true); }"></span>
</div>
</th>
<th>
<div class="th">
Operational
<span class="fa fa-angle-up" data-bind="click: function () { sortByFifthColumn(false); }"></span>
<span class="fa fa-angle-down" data-bind="click: function () { sortByFifthColumn(true); }"></span>
</div>
</th>
<th>
<div class="th">
Valid
<span class="fa fa-angle-up" data-bind="click: function () { sortBySixthColumn(false); }"></span>
<span class="fa fa-angle-down" data-bind="click: function () { sortBySixthColumn(true); }"></span>
</div>
</th>
</tr>
</thead>
<tbody data-bind="foreach: paginated">
<tr>
<td data-bind="text: $data.PartNumber"></td>
<td><a target="_blank" data-bind="text: $data.SerialNumber, click: function () { $root.setSerialNumberAndFindEquipment(SerialNumber) }" style="color:royalblue"></a></td>
<td data-bind="text: $data.Type"></td>
<td data-bind="text: $data.EquipmentGroup"></td>
<td>
<span data-bind="css: $root.operationalCss($data), text: $root.getOpStatus($data)"></span>
</td>
<td data-bind="text: $data.Validity"></td>
</tr>
</tbody>
</table>
<footer class="table-footer">
<div class="row">
<div class="col-md-6 page-num-info">
<span>Show <select style="min-width: 40px; max-width: 50px;" data-bind="options: selectResultsPerPage, value: resultsPerPage"></select> entries per page</span>
</div>
<div class="col-md-6 text-right pagination-container">
<ul class="pagination-sm pagination" data-bind="foreach: pages">
<li data-bind="if: $index() < 1"><a data-bind="click: $parent.toFirstPage">First</a> </li>
<li class="paginationLi"><a data-bind="text: displayValue, click: $parent.goToPage(iterator), css: { selected: isSelected }"></a></li>
<li data-bind="if: $parent.isLastIteration($index)"> <a data-bind="click: $parent.toLastPage">Last</a> </li>
</ul>
</div>
</div>
</footer>
</section>
【问题讨论】:
-
能否请您发布一个完整的、可运行的当前分页代码示例,最好在您的问题中使用Stackoverflow snippet 或JSFiddle?
-
我不知道如何获取数据,所以不确定如何使其可运行,但我会添加整个模型和表格
标签: javascript jquery css arrays knockout.js