Uncaught TypeError: grid.sortedData.peek(...). Фильтр не является функцией

Я пытаюсь сделать пейджинговую работу с KnockoutJs KOGrid. Я следил за этим: http://knockout-contrib.github.io/KoGrid/

Данные, которые я передаю в мою модель представления (параметр vm), содержат следующее:

Моя модель вида нокаута выглядит следующим образом:

function ViewModel(vm) {
    var self = this;
    this.myData = ko.observableArray([]);

    this.rows = ko.observableArray(vm.Rows);

    this.deleteInvisibleColumns = function () {
        for (var i = 0; i < vm.Rows.length; i++) {
            var row = vm.Rows[i];

            var keys = Object.keys(row);
            for (var k = 0; k < keys.length; k++) {
                if (vm.VisibleColumns.indexOf(keys[k]) === (-1)) {
                    delete row[keys[k]];
                };
            };
        };
    };  

    self.deleteInvisibleColumns();

    this.filterOptions = {
        filterText: ko.observable(""),
        useExternalFilter: true
    };

    this.pagingOptions = {
        pageSizes: ko.observableArray([2, 500, 1000]),
        pageSize: ko.observable(2),
        totalServerItems: ko.observable(0),
        currentPage: ko.observable(1)     
    };

    this.setPagingData = function(data, page, pageSize){    
        var pagedRows = data.Rows.slice((page - 1) * pageSize, page * pageSize);
        var pagedData = { Rows: pagedRows, VisibleColumns: data.VisibleColumns };

        self.myData(pagedData);
        self.pagingOptions.totalServerItems(data.Rows.length);
    };

    this.getPagedDataAsync = function (pageSize, page, searchText) {
        setTimeout(function () {
            var data;
            if (searchText) {
                var ft = searchText.toLowerCase();
                $.getJSON('/SampleData/GetDataPage', function (returnedPayload) {
                    data = returnedPayload.filter(function (item) {
                        return JSON.stringify(item).toLowerCase().indexOf(ft) != -1;
                    });
                    self.setPagingData(data,page,pageSize);
                });          
            } else {
                $.getJSON('/SampleData/GetDataPage', function (returnedPayload) {
                    self.setPagingData(returnedPayload, page, pageSize);
                });
            }
        }, 100);
    };

    self.filterOptions.filterText.subscribe(function (data) {
        self.getPagedDataAsync(self.pagingOptions.pageSize(), self.pagingOptions.currentPage(), self.filterOptions.filterText());
    });   

    self.pagingOptions.pageSizes.subscribe(function (data) {
        self.getPagedDataAsync(self.pagingOptions.pageSize(), self.pagingOptions.currentPage(), self.filterOptions.filterText());
    });
    self.pagingOptions.pageSize.subscribe(function (data) {
        self.getPagedDataAsync(self.pagingOptions.pageSize(), self.pagingOptions.currentPage(), self.filterOptions.filterText());
    });
    self.pagingOptions.totalServerItems.subscribe(function (data) {
        self.getPagedDataAsync(self.pagingOptions.pageSize(), self.pagingOptions.currentPage(), self.filterOptions.filterText());
    });
    self.pagingOptions.currentPage.subscribe(function (data) {
        self.getPagedDataAsync(self.pagingOptions.pageSize(), self.pagingOptions.currentPage(), self.filterOptions.filterText());
    });

    self.getPagedDataAsync(self.pagingOptions.pageSize(), self.pagingOptions.currentPage());

    this.gridOptions = {
        data: self.myData,
        enablePaging: true,
        pagingOptions: self.pagingOptions,
        filterOptions: self.filterOptions
    };  
};

Энди мой HTML (Asp.Net MVC Razor view):

@model ESB.BamPortal.Website.Models.SampleDataViewModel
@using System.Web.Script.Serialization
@{
    ViewBag.Title = "Sample Data";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>@ViewBag.Title</h2>
@{  string data = new JavaScriptSerializer().Serialize(Model); }

<div id="Knockout" data-bind="koGrid: gridOptions">
</div>



@section Scripts {
    <script src="~/KnockoutVM/SampleData.js"></script>
    <link rel="stylesheet" type="text/css" href="~/Content/KoGrid.css">
    <script type="text/javascript">
        var vm = new ViewModel(@Html.Raw(data));
        ko.applyBindings(vm, document.getElementById("Knockout"));
    </script>
}

Когда страница загружается, из kogrid.js выдается следующая ошибка. Uncaught TypeError : grid.sortedData.peek (...). Filter не является функцией

self.evalFilter = function () {
        if (searchConditions.length === 0) {
            grid.filteredData(grid.sortedData.peek().filter(function(item) {

Если я проверяю свойство sortedData объекта grid, оно выглядит нормально:

Последняя строка моей нокаутированной модели представления js для выполнения - это self.myData(pagedData); внутри функции this.SetPagingData.

Используя Fiddler, я извлек из ответа сервера следующее:

<script type="text/javascript">
        var vm = new ViewModel({"Rows":[{"SampleDataId":1,"Manufacturer":"Ford","Model":"Escort","Style":"Hatch"},{"SampleDataId":2,"Manufacturer":"Vauxhall","Model":"Cavalier","Style":"Saloon"},{"SampleDataId":3,"Manufacturer":"Rover","Model":"Montego","Style":"Saloon"},{"SampleDataId":4,"Manufacturer":"Ford","Model":"Escort","Style":"Hatch"},{"SampleDataId":5,"Manufacturer":"Vauxhall","Model":"Cavalier","Style":"Saloon"},{"SampleDataId":6,"Manufacturer":"Rover","Model":"Montego","Style":"Saloon"},{"SampleDataId":7,"Manufacturer":"Opel","Model":"Monza","Style":"Coupe"},{"SampleDataId":8,"Manufacturer":"BMW","Model":"325i","Style":"Saloon"},{"SampleDataId":9,"Manufacturer":"Ford","Model":"Escort","Style":"Hatch"},{"SampleDataId":10,"Manufacturer":"Vauxhall","Model":"Cavalier","Style":"Saloon"},{"SampleDataId":11,"Manufacturer":"Rover","Model":"Montego","Style":"Saloon"},{"SampleDataId":12,"Manufacturer":"Opel","Model":"Monza","Style":"Coupe"},{"SampleDataId":13,"Manufacturer":"BMW","Model":"325i","Style":"Saloon"},{"SampleDataId":14,"Manufacturer":"Ford","Model":"Escort","Style":"Hatch"},{"SampleDataId":15,"Manufacturer":"Vauxhall","Model":"Cavalier","Style":"Saloon"},{"SampleDataId":16,"Manufacturer":"Rover","Model":"Montego","Style":"Saloon"},{"SampleDataId":17,"Manufacturer":"Opel","Model":"Monza","Style":"Coupe"},{"SampleDataId":18,"Manufacturer":"BMW","Model":"325i","Style":"Saloon"},{"SampleDataId":19,"Manufacturer":"Ford","Model":"Escort","Style":"Hatch"},{"SampleDataId":20,"Manufacturer":"Vauxhall","Model":"Cavalier","Style":"Saloon"},{"SampleDataId":21,"Manufacturer":"Rover","Model":"Montego","Style":"Saloon"},{"SampleDataId":22,"Manufacturer":"Opel","Model":"Monza","Style":"Coupe"},{"SampleDataId":23,"Manufacturer":"BMW","Model":"325i","Style":"Saloon"}],"VisibleColumns":[]});
        ko.applyBindings(vm, document.getElementById("Knockout"));
    </script>

Где я неправ?

1 ответ

Решение

Вы правильно указываете ko.observableArray имущество (myData) как data параметр gridOptions объект, однако вы должны убедиться, что он всегда содержит массив JavaScript.

Knockout не "проверяет тип" того, что вы положили в ko.observableArray поэтому вам необходимо убедиться, что вы всегда используете массивы.

Однако в вашем setPagingData вы пытаетесь присвоить объект вашему myData вместо массива, и это выдает эту ошибку:

Uncaught TypeError: grid.sortedData.peek (...). Фильтр не является функцией

потому что простой объект JavaScript Litaral не имеет filter функция.

Исправить довольно просто, нужно просто пройти pagedData.Rows как значение myData:

this.setPagingData = function(data, page, pageSize){    
        var pagedRows = data.Rows.slice((page - 1) * pageSize, page * pageSize);
        var pagedData = { Rows: pagedRows, VisibleColumns: data.VisibleColumns };

        self.myData(pagedData.Rows);
        self.pagingOptions.totalServerItems(data.Rows.length);
    };

Sidenote: Ваша текущая реализация не выполняет надлежащую подкачку на стороне сервера. Потому что вы не передаете никаких параметров серверу и обрабатываете возвращенные данные на стороне клиента.

Другие вопросы по тегам