使用Web API在MVC中进行Knockout Paging

时间:2014-02-21 18:44:20

标签: asp.net-mvc knockout.js asp.net-web-api

我无法将此代码提供给页面。表的页面大小始终相同 - 从Web API调用返回的项目数。传入的参数被忽略(3)。此外,后退和前进按钮元素没有图标( icon-step-backward icon-step-forward ),但这是次要的页面大小。

HTML

<table class="table">
    <thead>
        <tr>
            <th data-column="LastName">Last Name</th>
            <th data-column="FirstName">First Name</th>
            <th data-column="EnrollmentDate">Enrollment Date</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: students">
        <tr>
            <td data-bind="text: LastName" />
            <td data-bind="text: FirstName" />
            <td data-bind="text: EnrollmentDate" />
        </tr>
    </tbody>

    <tfoot>
        <tr>
            <td>
                Number of items per page:
                <select id="pageSizeSelector" data-bind="value: pageSize">
                    <option value="1">1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                    <option value="4">4</option>
                    <option value="5">5</option>
                    <option value="6">6</option>
                    <option value="7">7</option>
                    <option value="8">8</option>
                    <option value="9">9</option>
                    <option value="10">10</option>
                </select>
            </td>
            <td colspan="3">
                <button data-bind="click: previousPage" class="btn"><i class="icon-step-backward"></i></button>
                Page<label data-bind="text: currentPageIndex() + 1" class="badge"></label>
                <button data-bind="click: nextPage" class="btn"><i class="icon-step-forward"></i></button>
            </td>
        </tr>
    </tfoot>
</table>

坚决和观察

<script type="text/javascript">

    var viewModel = function () {
        self = this;
        self.currentPage = ko.observable();
        self.pageSize = ko.observable(3);
        self.currentPageIndex = ko.observable(0);
        self.students = ko.observableArray();
        self.currentPage = ko.computed(function () {
            var pagesize = parseInt(self.pageSize(), 3),
            startIndex = pagesize * self.currentPageIndex(),
            endIndex = startIndex + pagesize;
            return self.students.slice(startIndex, endIndex);
        });

        self.nextPage = function () {
            if (((self.currentPageIndex() + 1) * self.pageSize()) < self.students().length) {
                self.currentPageIndex(self.currentPageIndex() + 1);
            }
            else {
                self.currentPageIndex(0);
            }
        }
        self.previousPage = function () {
            if (self.currentPageIndex() > 0) {
                self.currentPageIndex(self.currentPageIndex() - 1);
            }
            else {
                self.currentPageIndex((Math.ceil(self.students().length / self.pageSize())) - 1);
            }
        }
    }

    $(document).ready(function () {
        $.ajax({
            url: "http://localhost:12769/api/student",
            type: "GET"
        }).done(function (data) {
            var vm = new viewModel();
            vm.students(data);
            ko.applyBindings(vm);
        }).error(function (jqXHR, textStatus, errorThrown) {
            alert(jqXHR.responseText || textStatus);
        });
    });

</script>

从Web API返回的JSON

[{"$id":"1","ID":1,"LastName":"Alexander","FirstMidName":"Carson","EnrollmentDate":"2005-09-01T00:00:00","Enrollments":[{"$id":"2","EnrollmentID":1,"CourseID":1050,"StudentID":1,"Grade":0,"Course":{"$id":"3","CourseID":1050,"Title":"Chemistry","Credits":3},"Student":{"$ref":"1"}},{"$id":"4","EnrollmentID":2,"CourseID":4022,"StudentID":1,"Grade":2,"Course":{"$id":"5","CourseID":4022,"Title":"Microeconomics","Credits":3},"Student":{"$ref":"1"}},{"$id":"6","EnrollmentID":3,"CourseID":4041,"StudentID":1,"Grade":1,"Course":{"$id":"7","CourseID":4041,"Title":"Macroeconomics","Credits":3},"Student":{"$ref":"1"}}]},{"$id":"8","ID":2,"LastName":"Alonso","FirstMidName":"Meredith","EnrollmentDate":"2002-09-01T00:00:00","Enrollments":[{"$id":"9","EnrollmentID":4,"CourseID":1045,"StudentID":2,"Grade":1,"Course":{"$id":"10","CourseID":1045,"Title":"Calculus","Credits":4},"Student":{"$ref":"8"}},{"$id":"11","EnrollmentID":5,"CourseID":3141,"StudentID":2,"Grade":4,"Course":{"$id":"12","CourseID":3141,"Title":"Trigonometry","Credits":4},"Student":{"$ref":"8"}},{"$id":"13","EnrollmentID":6,"CourseID":2021,"StudentID":2,"Grade":4,"Course":{"$id":"14","CourseID":2021,"Title":"Composition","Credits":3},"Student":{"$ref":"8"}}]},{"$id":"15","ID":3,"LastName":"Anand","FirstMidName":"Arturo","EnrollmentDate":"2003-09-01T00:00:00","Enrollments":[{"$id":"16","EnrollmentID":7,"CourseID":1050,"StudentID":3,"Grade":null,"Course":{"$ref":"3"},"Student":{"$ref":"15"}}]},{"$id":"17","ID":4,"LastName":"Barzdukas","FirstMidName":"Gytis","EnrollmentDate":"2002-09-01T00:00:00","Enrollments":[{"$id":"18","EnrollmentID":8,"CourseID":1050,"StudentID":4,"Grade":null,"Course":{"$ref":"3"},"Student":{"$ref":"17"}},{"$id":"19","EnrollmentID":9,"CourseID":4022,"StudentID":4,"Grade":4,"Course":{"$ref":"5"},"Student":{"$ref":"17"}}]},{"$id":"20","ID":5,"LastName":"Li","FirstMidName":"Yan","EnrollmentDate":"2002-09-01T00:00:00","Enrollments":[{"$id":"21","EnrollmentID":10,"CourseID":4041,"StudentID":5,"Grade":2,"Course":{"$ref":"7"},"Student":{"$ref":"20"}}]},{"$id":"22","ID":6,"LastName":"Justice","FirstMidName":"Peggy","EnrollmentDate":"2001-09-01T00:00:00","Enrollments":[{"$id":"23","EnrollmentID":11,"CourseID":1045,"StudentID":6,"Grade":null,"Course":{"$ref":"10"},"Student":{"$ref":"22"}}]},{"$id":"24","ID":7,"LastName":"Norman","FirstMidName":"Laura","EnrollmentDate":"2003-09-01T00:00:00","Enrollments":[{"$id":"25","EnrollmentID":12,"CourseID":3141,"StudentID":7,"Grade":0,"Course":{"$ref":"12"},"Student":{"$ref":"24"}}]},{"$id":"26","ID":8,"LastName":"Olivetto","FirstMidName":"Nino","EnrollmentDate":"2005-09-01T00:00:00","Enrollments":[]}]

1 个答案:

答案 0 :(得分:6)

它可能不适合您的一个原因是,您使用基数为3的parseInt。因此,在currentPage ko计算中,行var pagesize = parseInt(self.pageSize(), 3)将转到结果为NaN。有关详细信息,请参阅MDN docs

这是一个有用的KO可观察数组的分页扩展,它也会清理你的视图模型。有关工作示例,请参阅此fiddle。在您的情况下,您的viewmodel将只是

var viewmodel = function(){
     var self = this;
     self.students = ko.observableArray().paged(3);
}

你的HTML就是这样:

<table data-bind="foreach: students.pagedItems">
    <!-- normal data binding syntax here -->
</table>

还有一些分页控件。这些是使用Bootstrap类,但是让您了解如何使用它们:

<ul class="pagination">
    <li data-bind="css: { disabled: students.currentPageIndex() === 0 }"><a href="#" data-bind="click: students.previousPage">&laquo;</a></li>
</ul>
<ul class="pagination" data-bind="foreach: students.allPages">
    <li data-bind="css: { active: pageNumber === ($root.students.currentPageIndex() + 1) }">
        <a href="#" data-bind="text: pageNumber, click: function() { $root.students.moveToPage(pageNumber-1); }"></a>
    </li>
</ul>
<ul class="pagination">
    <li data-bind="css: { disabled: students.currentPageIndex() === students.maxPageIndex() }"><a href="#" data-bind="click: students.nextPage">&raquo;</a></li>
</ul>
<br />
<span data-bind="text: students.currentStatus"></span>

这是扩展名。我有第二个选项来传递排序函数,但它完全是可选的。

ko.observableArray.fn.paged = function (perPage, sortComparator) {
            var items = this;

            items.currentPage = ko.observable();
            items.pageSize = ko.observable(perPage);
            items.currentPageIndex = ko.observable(0);

            items.currentItemPage = ko.computed(function () {
                var pagesize = parseInt(items.pageSize(), 10),
                    startIndex = pagesize * items.currentPageIndex(),
                    endIndex = startIndex + pagesize;
                return this().slice(startIndex, endIndex);
            }, items);

            items.pagedItems = ko.computed(function () {
                var size = parseInt(items.pageSize(), 10),
                    start = items.currentPageIndex() * size;

                if (typeof (sortComparator) === "function") {
                    var sorted = this().sort(sortComparator);
                    return sorted.slice(start, start + size);
                } else {
                    return this().slice(start, start + size);
                }


            }, items);

            items.maxPageIndex = ko.computed(function () {
                return Math.ceil(this().length / items.pageSize()) - 1;
            }, items);

            items.allPages = ko.computed(function () {
                var pages = [];
                for (var i = 0; i <= items.maxPageIndex() ; i++) {
                    pages.push({ pageNumber: (i + 1) });
                }
                return pages;
            }, items);

            items.currentStatus = ko.computed(function () {
                var pagesize = parseInt(items.pageSize(), 10),
                    start = pagesize * items.currentPageIndex(),
                    end = start + pagesize;

                if (items.currentPageIndex() === items.maxPageIndex()) end = this().length;

                return 'Showing ' + (start + 1) + ' to ' + end + ' of ' + this().length;
            }, items);

            items.nextPage = function () {
                if (((items.currentPageIndex() + 1) * items.pageSize()) < items().length) {
                    items.currentPageIndex(items.currentPageIndex() + 1);
                } else {
                    items.currentPageIndex(0);
                }
            };

            items.previousPage = function () {
                if (items.currentPageIndex() > 0) {
                    items.currentPageIndex(items.currentPageIndex() - 1);
                } else {
                    items.currentPageIndex((Math.ceil(items().length / items.pageSize())) - 1);
                }
            };

            items.moveToPage = function (index) {
                items.currentPageIndex(index);
            };

            return items;
        };