如何使用knockout同时应用过滤和分页?

时间:2014-08-26 06:47:27

标签: javascript jquery html css knockout.js

我一直在玩knockoutjs尝试创建可以过滤和分页的html表到目前为止我已经能够分别创建过滤和分页但似乎我找不到一种方法来组合两个在一起我把两个例子我已经取得了任何帮助将是非常感谢提前:)

淘汰赛过滤示例:

Filtering Example

HTML:

<table id="tview" class="table table-bordered table-striped table-hover">
    <thead>
        <tr>
            <td>ID</td>
            <td>Name</td>
        </tr>
        <tr>
            <td>
                <input type="number" data-bind="event: { keyup: FilterItems }" id="ID" class="form-control filter" placeholder="Filter By ID" />
            </td>
            <td>
                <input type="text" data-bind="event: { keyup: FilterItems }" id="Name" class="form-control filter" placeholder="Filter By Name" />
            </td>
        </tr>
    </thead>
    <tbody data-bind="foreach: $root.FilteredItem">
        <td data-bind="text: ID"></td>
        <td data-bind="text: Name"></td>
    </tbody>
</table>

使用Javascript:

var model = function () {
    var self = this;
    self.Item = ko.observableArray([]);
    self.FilteredItem = ko.observableArray([]);
    self.Filter = new Filter();
    self.FilterItems = function (object, event) {
        var currentFilter = event.currentTarget.id;
        var currentValue = $("#" + currentFilter).val();
        if (currentValue != "") {
            if (self.Filter.ActiveList().indexOf(currentFilter) < 0) {
                self.Filter[currentFilter](true);
                self.Filter.ActiveList.push(currentFilter);
            }
            self.ApplyFilters();
        } else {
            self.Filter[currentFilter](false);
            self.Filter.ActiveList.remove(currentFilter);
            if (self.Filter.ActiveList().length == 0) {
                self.FilteredItem(self.Item());
            } else {
                self.ApplyFilters();
            }
        }
    };

    self.ApplyFilters = function () {
        var tempArray = self.Item();
        self.Filter.ActiveList().forEach(function (item) {
            var value = $("#" + item).val();
            var FilterResult = [];
            if (isNaN(value)) {
                value = value.toLowerCase();
                FilterResult = ko.utils.arrayFilter(tempArray, function (obj) {
                    return obj[item]().toLowerCase().indexOf(value) > -1;
                });
            } else {
                FilterResult = ko.utils.arrayFilter(tempArray, function (obj) {
                    if (isNaN(obj[item]())) {
                        return obj[item]().toLowerCase().indexOf(value) > -1;
                    } else {
                        return obj[item]() == value;
                    }
                });
            }
            tempArray = FilterResult;
            self.FilteredItem(FilterResult);
        });
    };
};

var Item = function () {
    var self = this;
    self.ID = ko.observable();
    self.Name = ko.observable();
};

var Filter = function () {
    var self = this;
    self.ActiveList = ko.observableArray([]);
    self.ID = ko.observable(false);
    self.Name = ko.observable(false);
};

var modelInstance = new model();

for (i = 0; i < 10; i++) {
    var MyItem = new Item();
    MyItem.ID(i);
    MyItem.Name("Name" + i);
    modelInstance.Item.push(MyItem);
    MyItem = new Item();
    MyItem.ID(i);
    MyItem.Name("Name" + i+1);
    modelInstance.Item.push(MyItem);
}

modelInstance.FilteredItem(modelInstance.Item());

ko.applyBindings(modelInstance);


淘汰分页示例:

Paging Example

HTML:

<section data-bind="foreach: Pages">
    <article  data-bind="visible: $root.CurrentPage() == $data">
        <table id="tview" class="table table-bordered table-striped table-hover">
            <thead>
                <tr>
                    <td>ID</td>
                    <td>Name</td>
                </tr>
            </thead>
            <tbody data-bind="foreach: $root.Item()[$data]">
                <tr>
                    <td data-bind="text: ID"></td>
                    <td data-bind="text: Name"></td>
                </tr>
            </tbody>
        </table>
    </article>
</section>
<ul class="pagination" data-bind="foreach: Pages">
    <li data-bind="attr: { id: 'Page' + $index(), 'class': $root.checkCurrentPage($data) }, click: $root.ChangePage"><a href="#" data-bind="text: $data"></a>
    </li>
</ul>

使用Javascript:

var Model = function () {
    var self = this;

    self.Item = ko.observableArray([]);

    self.CurrentPage = ko.observable(0);

    self.Pages = ko.observableArray([]);

    self.ChangePage = function (data, event) {
        if (!$(event.currentTarget).hasClass("active")) {
            $(".pagination li").removeClass("active");
            self.CurrentPage(data);
        }
    };

    self.checkCurrentPage = function (data) {
        if (self.CurrentPage() == data) {
            return "active";
        }
    };
};

var Item = function () {
    var self = this;
    self.ID = ko.observable();
    self.Name = ko.observable();
};

var modelInstance = new Model();

function Chunk(Arr, ChunkSize) {
    var Set = [];

    var PageCount = 0;

    for (var Page = 0; Page < Arr.length; Page += ChunkSize) {
        var TempArr = Arr.slice(Page, Page + ChunkSize);

        var ObservableItemArr = [];

        TempArr.forEach(function (obj) {
            ObservableItemArr.push(obj);
        });

        Set.push(ko.observableArray(ObservableItemArr));

        modelInstance.Pages.push(PageCount);

        PageCount++;
    }

    return Set;
}

var arr = [];

for (i = 0; i < 20; i++) {
    var MyItem = new Item();
    MyItem.ID(i);
    MyItem.Name("Name" + i);
    arr.push(MyItem);
    MyItem = new Item();
    MyItem.ID(i);
    MyItem.Name("Name" + i+1);
    arr.push(MyItem);
}

modelInstance.Item(Chunk(arr, 10));

ko.applyBindings(modelInstance);

1 个答案:

答案 0 :(得分:3)

这是我用LinqJS做的快速小提琴

http://jsfiddle.net/rL6p4onw/2

结构看起来像这样

ViewModel = function() {
    var items = [];
    for(var i = 0; i < 500; i++) {
        items.push({ name: "Foo " + i });
    }

    this.items = Enumerable.From(items);   

    this.page = ko.observable(0);
    this.pageSize = ko.observable(10);
    this.filter = ko.observable();
    this.filteredCount = ko.observable();

    this.currentPage = ko.computed(this.getCurrentPage, this);
    this.pages = ko.computed(this.getPages, this);
}

分页/过滤的相关代码

getCurrentPage: function() {   
    var filter = this.filter();

    var filtered = this.items
        .Where(function(i) { 
            return filter == null || i.name.indexOf(filter) != -1; 
        });

    this.filteredCount(filtered.Count());
    return filtered
        .Skip(this.page() * this.pageSize())
        .Take(this.pageSize())
    .ToArray();
}

由于javascript是动态的,因此可以轻松地将过滤器功能修改为动态