How do I load data into Kendo UI Grid using server side paging?

ⅰ亾dé卋堺 提交于 2020-01-07 06:33:06

问题


I have the following code that builds a kendo ui grid:

    // build grid columns

    // the check box column is always visible for all users
    var columns = [{
        field:'<input id="masterCheck" class="check" type="checkbox" /><label for="masterCheck"></label>', 
        template: '<input class="check rowSelect" id="${id}" type="checkbox" /><label for="${id}"></label>',
        filterable: false,
        width: 33,
        sortable: false // may want to make this sortable later. will need to build a custom sorter.
    }];

    // build the rest of the columns using data provided by the server
    var metrics = initialData.metric;
    for (var i=0; i < metrics.length; i++) {
        var metric = metrics[i];
        var column = {};
        column.field = metric.qualifiedName;
        column.title = metric.label;
        column.width = metric.colWidth;
        // initially hide all columns. we'll know exactly which ones to show after a search
        column.hidden = true;        
        column.type = metric.type;

        // handle special considerations
        if (column.type === 'float' || column.type === 'int') {        

            // format all floats to two decimal places
            if (column.type === 'float') {
                column.format = '{0:n2}';
            }
            // the grid only has a type of number.            

            column.attributes = {'class' : 'right-align'};

            var field = column.field;

            // create a closure to build a function that captures the field variable value
            // in this iteration. Immediately execute the anonymous outer function so 
            // that the inner function is returned as assignment to the footerTemplate
            // variable. The param data will be passed to the function by the grid.
            // That function then executes the buildFooter which has the right field value
            // due to the closure. notice that each invocation of the outer function
            // creates a new scope chain that adds a new inner function.
            column.footerTemplate = (function(field, columnType) {return function() { return buildFooter(field, columnType); }; })(field, metric.type);
            column.type = 'number';

        } else if (column.type === 'date') {
            column.format = '{0:yyyy-MM-dd}';
        } else if (column.field === 'attachments') {
            //column.field = 'text';
            // use a template defined in search.jsp to style this complex
            // object
            column.template = kendo.template($('#attachmentTemplate').html());
            column.sortable = false;
            column.filterable = false;
        } else if (column.type === 'list') {
            column.type = 'string';
        }

        columns.push(column);        
    }

    var toolbarItems = [{ name: 'custom', text: 'Filter', className: 'filterClass k-state-disabled', imageClass: 'k-icon k-i-funnel'},
                        { name: 'view', text: 'View', className: 'viewClass k-state-disabled', imageClass: 'k-icon k-i-search' }];
    // only show build the edit and delete buttons in the toolbar if the
    // user has permissions
    if ($('#hasAdminControls')[0]) {
        toolbarItems.push({ name: 'edit', text: 'Edit', className: 'editClass k-state-disabled' });
        toolbarItems.push({ name: 'destroy', text: 'Delete', className: 'deleteClass k-state-disabled' });
    }

    var options = {

        autoBind: false,
        dataBound: function() {

            alert('dataBound');
            for(var i =0; i <  checkedRows.length; i++){
                $('#'+ checkedRows[i]).attr('checked','checked');
            }            
            $('.rowSelect').click(setGridControlsState);
            setGridControlsState();

            $('.k-grid-content').removeHighlight();
            $('.k-grid-content').highlight(uniqueHighlights);
        },    
         dataSource: {
            //type: 'json',
            //batch: 'true',
            serverPaging: true, // we may need to use paging for performance reasons
            //schema: {
            //    total: 'total'//function(response) { console.log(response); alert('hi2'); return 500; }
            //},
            //schema: {
                //model: Acquisition // if we use a model then complex objects' fields all have string type

            pageSize: 10, 

            //serverFiltering: true, // we may want to use this in the future if client filtering becomes a performance issue
            //serverSorting: true, // we may want to use this in the future if client sorting becomes a performance issue
            transport: { read: 
            function(options) {

                var setupOptions = { 
                        success: function(data, statusText, xhr, $form) {options.success(data); loadSearch(data, statusText, xhr, $form)},
                        type: 'POST',
                        dataType: 'json',
                        data: {skip: options.data.skip, take: options.data.take},
                        url:   '../search.x',
                        error: errorHandler.handle,
                        timeout: 50000
                };
                $('#searchForm').ajaxSubmit(setupOptions);
            }

            }
        },
        height: 600,
        pageable: {
            //numeric: false,
            //previousNext: false,
            messages: {
                display: "{2} Acquisitions"
            },
            pageSizes: true
        },
        sortable: true,
        resizable: true,
        filterable: true,
        toolbar: toolbarItems,
        columns: columns
    };

    // create the grid using the above options
    $('#resultsGrid').kendoGrid(options);

    // for purely aesthetic purposes, move the toolbar to the bottom (by default it's at the top) 
    $('#resultsArea').find('.k-grid-toolbar').insertAfter($('#resultsArea .k-grid-footer'));
    var grid = $('#resultsGrid').data('kendoGrid');
    grid.refresh();

The grid is initially hidden but shows after a search form is submitted. When the search form is submitted, the following function is executed:

function startSearch(evt) {
    evt.preventDefault();

    showLoadingGrid();
    var grid = $('#resultsGrid').data('kendoGrid');
    grid.dataSource.read();

}

The grid.dataSource.read() function call will result in the AJAX call to the server initiated by transport.read. However, the success function never gets called because kendo throws an error. It states d.oneOfMyObjects is undefined kendo.web.min.js (line 9). When I look at the json response, I have several json objects from the server. One of the objects is an array of objects. Each of those objects has an property (which is an object) called oneOfMyObjects. Each oneOfMyObjects is non-null. So, I'm not sure why kendo is failing. I'm using kendoui.2012.3.1315. How can I stop kendo from throwing this error and allow my loadSearch callback function to be called?

2nd EDIT The error is occurring in the success function at options.success(data);

EDIT Editing question to contain the output from server. Please note that the same output works fine without sever pagination (also had to modify output for data security purposes... I tried to keep the same structure though but hopefully I did not accidentally change to make it non-JSON compliant):

{
    "total":500,
    "displayFields":["summary","page","take","pageSize","skip"],
    "object":[{
        "id":16835,
        "date":-2208967200000,
        "type":"Needs Value",
        "nestedObject1":{
            "id":16870,
            "name":"Not Specified",
            "region":{
                "name":"Needs Value"
            }
        },
        "oneOfMyObjects":{
            "id":16923,
            "name":"Needs Value"
        }
    }, {
        "id":16836,
        "date":-2208967200000,
        "type":"Needs Value",
        "nestedObject1":{
            "id":16873,
            "name":"Not Specified",
            "region":{
                "name":"Needs Value"
            }
        },
        "oneOfMyObjects":{
            "id":16925,
            "name":"Needs Value"
        }
    }, /* 8 more records */]
}

3rd edit to include loadSearch function

function loadSearch(data, statusText, xhr, $form, options) {

    if (data.validationError) {
        // TODO we need to look at the message from the reply
        // right now though only date validation errors will exist
        dialog.show('Error', 'Please enter dates formatted as yyyy-mm-dd.');
        global.loadingIndicator.hide();
        return;
    }

    checkedRows = [];
    var object= data.object;

    var grid = $('#resultsGrid').data('kendoGrid');

    // clear any filters. This also help with an issue where no 
    // rows are shown due to a filter.
    grid.dataSource.filter({});


    // set the search results data in the grid
    grid.dataSource.data(object);

    // show columns that are either a user preference
    // column (or default set if user has no preferences)
    // or a field matching search data

    // let's only hide/show the delta between
    // previously viewed cols and new cols to display 
    // since it's much faster than hiding all old
    // and then displaying all new cols
    var oldCols = $('#displayColumns').val() || [];

    // the server tells the UI which fields to display
    // based on user preference and fields that that
    // have matching search data
    var newCols = data.displayFields;

    var removedCols = oldCols.diff(newCols);
    for (var i in removedCols) {
        $('#displayColumns option[value="' + removedCols[i] + '"]').removeAttr('selected');
        grid.hideColumn(removedCols[i]);
    }

    var addedCols = newCols.diff(oldCols);
    for (var i in addedCols) {
        grid.showColumn(addedCols[i]);
        $('#displayColumns option[value="' + addedCols[i] + '"]').attr('selected', 'selected');
    }

    // we have to tell the chosen overlay that we updated the list
    $('#displayColumns').trigger('liszt:updated');

    // we have to keep track of the current selected values
    // so that when the user changes to selection we'll 
    // be able to compare to the original selection
    // and now what they changed.
    $('#displayColumns').data('chosen-values', $('#displayColumns').val());


    // display the results
    grid.refresh();

    realignFooter();

    // Highlight search matches so the user can easily see
    // why the record is in the result grid.
    // Unfortunately, the highlights library takes a comma-delimited list.
    // It's problematic when the search results contain a comma.


    // remove previous highlights
    //$('.k-grid-content').removeHighlight();

    uniqueHighlights = data.uniqueHighlights || [];
    $('.k-grid-content').removeHighlight();
    $('.k-grid-content').highlight(uniqueHighlights);

    // reset the controls since all checkboxes have been cleared
    setGridControlsState();

    // register event to capture clicks on grid checkboxes
    // we can't do this during initialization b/c the checkboxes
    // are not yet built. Note: we don't have to remove
    // the events associated with previous checkboxes as 
    // jquery should automatically do this.
    $('.rowSelect').click(setGridControlsState);

    // remove loading indicator
    global.loadingIndicator.hide();

    // style the UI to give the user an option to save the columns again
    $('#saveCols > span').empty().text('Save Columns');
    $('#saveCols').removeClass('k-state-disabled');

}

回答1:


You are not specifying in schema where to find the data. You need to say something as:

schema   : {
    data : "object",
    total: "total"
}

The fact that you are not saying where to find the results makes imposible then displaying any field.

Regarding the success function never gets called, such option does not exist (AFAIK).




回答2:


I would of just made this as a comment to clarify what would be useful to you but it would of been harder to see the code so I'll start this and see if I can fully answer your question.

transport: {
    read: {
        url: '@Url.Action("_List", "Check")',
        data: gridParams,
        type: 'POST'
    },
function gridParams() {
        return {
            Field1: $('#fd1').val(),
            Field2: $('#fd2').val(),
            Field3: $('#fd3').val()
        };
    }

fd1-3 would be your search forms Id's for it's fields which you need to pass in the parameters to your controller.

Then for your controller action,

[HttpPost]
    public JsonResult _List(string Field1, DateTime? Field2, DateTime? Field3, int skip, int take)
    {

Then your would just use these parameters to alter your db.TableName.Where(w => w.fd1 == Field1 && w.fd2 == Field2 || w.fd3 == Field3).Skip(skip)

So on and so forth.




回答3:


  var dataSource = new kendo.data.DataSource({
      serverPaging: true,
      serverSorting: true,
      pageSize : 15,
      transport : {
         read : {
           url : getEmployeeData,
           dataType : "json"
         },
         parameterMap : function(options, operation) {
            if (operation == "read") {
                return {
                  page: dataSource._page,
                  pageSize: dataSource._pageSize
            };
         }
      }
    },
    batch : true,
    schema : {
      data: "data",
      total: "total",
      model : {
        id : "id",
        fields : {
          name : {
            validation : {
              required : true
            }
          }
        }
      }
    }
  });


来源:https://stackoverflow.com/questions/16225218/how-do-i-load-data-into-kendo-ui-grid-using-server-side-paging

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!