Telerik Kendo MVC Grid - How do I set onload/initi

2019-09-11 10:30发布

问题:

I've been charged with changing my company's current webforms site pages to MVC. We use the Telerik tools package and I am looking for a way to set an initial filter on my grid so that when the page is loaded the grid defaults to showing only records that are checked (true). I have found several questions similar to this but so far none of the answers I have found in those instances dealt with checkboxes.

The code below is my "Active?" = True/False column in the MVC grid. I'm checking the deleted date for each record, which is treated as "deactivated" when a delete date exists. My user-initiated filtering works great on the grid but I am having trouble figuring out how to set the initial filter value on this column to TRUE while also allowing the user to clear the filter to then view deactivated records along with the active records.

I appreciate any help you can offer. If I'm implementing this completely wrong, feel free to let me know, but please also include an example of the correct way to accomplish this functionality.

columns.Bound("DeleteDateUTC")
     .ClientTemplate("<input type='checkbox' #= kendo.parseDate(DeleteDateUTC) ? '' : checked='checked' # disabled='disabled' />")
     .Title("Active?")
     .Filterable(ftb => ftb.Cell(cell => cell.Operator("Is equal to")))
     .Width(100);

Thank you!

EDIT 1:

<div id="gridArea" class="k-virtual-scrollable-wrap">
@(Html.Kendo().Grid<dynamic>()
    .Name("OperatorsGrid")
    .Mobile(MobileMode.Auto)
    .Pageable(pager => pager.PageSizes(new int[] { 50, 100, 250 })
                                    .Refresh(true))
    .Sortable()
    .Resizable(resize => resize.Columns(true))
    .HtmlAttributes(new { style = "height: 800px;" })
    .Scrollable()
    .ColumnMenu()
    .Filterable(ftb => ftb.Mode(GridFilterMode.Row))
    .Events(e => e.DataBound("onDataBound").Cancel("onCancel"))
    .DataSource(dataSource => dataSource
        .Ajax()
        .Model(model =>
        {
            model.Id("ID");
        })
        .PageSize(100)
        .Read(read => read.Action("Operators_Read", "TableMx"))
    )
    .Columns(columns =>
    {
        columns.Command(cmd => cmd.Custom("Operators_Edit").Text(" ").Click("edit"))
            .Title("Edit")
            .Width(75);
        columns.Command(cmd => cmd.Custom("Operators_Deactivate").Text(" ").Click("deactivate"))
            .Title("Deactivate")
            .Width(100);
        columns.Bound("DeleteDateUTC")
            .ClientTemplate("<input type='checkbox' #= kendo.parseDate(DeleteDateUTC) ? '' : checked='checked' # disabled='disabled' />")
            .Title("Active?")
            .Filterable(ftb => ftb.Cell(cell => cell.Operator("Is equal to")))
            .Width(100);
        columns.Bound("Name")
            .Filterable(ftb => ftb.Cell(cell => cell.Operator("contains")))
            .Title("Name")
            .Width(350);
        columns.Bound("Address")
            .Filterable(ftb => ftb.Cell(cell => cell.Operator("contains")))
            .Title("Address")
            .Width(250);
        columns.Bound("City")
            .Filterable(ftb => ftb.Cell(cell => cell.Operator("contains")))
            .Title("City")
            .Width(150);
        columns.Bound("StateAbbrev")
            .Filterable(ftb => ftb.Cell(cell => cell.ShowOperators(false)))
            .Title("State")
            .Width(100);
        columns.Bound("Zip")
            .Filterable(false)
            .Title("Zip")
            .Width(70);
        columns.Bound("ContactName")
            .Filterable(ftb => ftb.Cell(cell => cell.Operator("contains")))
            .Title("Contact Name")
            .Width(175);
        columns.Bound("ContactEmail")
            .Filterable(ftb => ftb.Cell(cell => cell.Operator("contains")))
            .Title("Email")
            .Width(175);
        columns.Bound("ContactPhone")
            .Filterable(ftb => ftb.Cell(cell => cell.ShowOperators(false)))
            .Title("Phone")
            .Width(150);
        columns.Bound("CreateDateUTC")
            .ClientTemplate("#= kendo.parseDate(CreateDateUTC) ? (kendo.toString(kendo.parseDate(CreateDateUTC), 'MM/dd/yyyy h:mm tt')) : '' #")
            .Title("Create Date UTC")
            .Width(250);
        columns.Bound("CreatedByUser")
            .Title("Created By")
            .Width(150);
        columns.Bound("LastChangeDateUTC")
            .ClientTemplate("#= kendo.parseDate(LastChangeDateUTC) ? (kendo.toString(kendo.parseDate(LastChangeDateUTC), 'MM/dd/yyyy h:mm tt')) : '' #")
            .Title("Last Update Date UTC")
            .Width(250);
        columns.Bound("LastChangedByUser")
            .Title("Last Updated By")
            .Width(150);
        columns.Bound("DeleteDateUTC")
            .ClientTemplate("#= kendo.parseDate(DeleteDateUTC) ? (kendo.toString(kendo.parseDate(DeleteDateUTC), 'MM/dd/yyyy h:mm tt')) : '' #")
            .Title("Deleted Date UTC")
            .Width(250);
        columns.Bound("DeletedByUser")
            .Title("Deleted By")
            .Width(150);
    })                
)

EDIT 2: Adding script section below grid. I'm not sure if this is required in order to help me out but it can't hurt to see everything that's going on.

<script>
$(function () {
    var grid = $("#OperatorsGrid").data("kendoGrid");

    //Save personalized settings for this grid (columns shown, etc.)
    $("#save").click(function (e) {
        e.preventDefault();
        localStorage["kendo-grid-options"] = kendo.stringify(grid.getOptions());
    });

    //If the user has saved options, load them.  Otherwise, load the default filter for the active column
    var options = localStorage["kendo-grid-options"];
    if (options) {
        grid.setOptions(JSON.parse(options));
    }
    else {
        grid.dataSource.filter({ field: "Active?", operator: "eq", value: "checked" });
    }

    //Remove column menu from any columns specified by data-title below:
    //grid.thead.find("[data-title=columnTitleHere]>.k-header-column-menu").remove();
    grid.thead.find("[data-title=\"Active?\"]>.k-header-column-menu").remove();
});

function deactivate(e) {
    e.preventDefault();
    var id = this.dataItem($(e.currentTarget).closest("tr")).id;
    var url = "/TableMx/Operators_Deactivate/" + id;
    $.ajax({
        type: "POST",
        url: url,
    })
    .done(function () {
        // refresh the grid to remove the just deactivated order
        refreshGrid();
    })
    .fail(function () { alert("failure deactivating operator") })
}

function edit(e) {        

}

function onDataBound(e) {        
    $(".k-grid-Operators_Deactivate span").addClass("k-icon k-delete ob-icon-only");
    $(".k-grid-Operators_Edit span").addClass("k-icon k-edit ob-icon-only");
}

function onCancel(e) {
    e.preventDefault();
    e.sender.refresh();
}

function refreshGrid() {
    if ($(".k-i-refresh").length > 0) {
        $(".k-i-refresh").trigger('click');
    }
}

回答1:

Instead of using a dynamic model, create a view model like this:

public class OperatorViewModel
{
    // I'm not sure if your ID is int or string...
    public int ID { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }

    // All the other properties here
    // ...
    // ...

    [Display(Name = "Active?")]    
    public bool IsActive { get; set; }
}

As you see, I also added an IsActive property to the view model. You'll populate this property in your Controller, depending on whether there is a DeleteDateUTC or not.

Then, your grid will be like (Note the .Filter I added to your data source):

@(Html.Kendo().Grid<YourApp.ViewModels.OperatorViewModel>()
    .Name("OperatorsGrid")
    .Mobile(MobileMode.Auto)
    .Pageable(pager => pager.PageSizes(new int[] { 50, 100, 250 })
                                    .Refresh(true))
    .Sortable()
    .Resizable(resize => resize.Columns(true))
    .HtmlAttributes(new { style = "height: 800px;" })
    .Scrollable()
    .ColumnMenu()
    .Filterable(ftb => ftb.Mode(GridFilterMode.Row))
    .Events(e => e.DataBound("onDataBound").Cancel("onCancel"))
    .DataSource(dataSource => dataSource
        .Ajax()
        .Model(model =>
        {
            model.Id("ID");
        })
        // THIS IS WHERE YOU FILTER THE IsActive FIELD
        .Filter(f => f.Add(m => m.IsActive.Equals(true)))
        .PageSize(100)
        .Read(read => read.Action("Operators_Read", "TableMx"))
    )
    .Columns(columns =>
    {
        columns.Command(cmd => cmd.Custom("Operators_Edit").Text(" ").Click("edit"))
            .Title("Edit")
            .Width(75);
        columns.Command(cmd => cmd.Custom("Operators_Deactivate").Text(" ").Click("deactivate"))
            .Title("Deactivate")
            .Width(100);
        columns.Bound(c => c.IsActive)
            .ClientTemplate("<input type='checkbox' #= IsActive ? '' : checked='checked' # disabled='disabled' />")
            .Filterable(ftb => ftb.Cell(cell => cell.Operator("Is equal to")))
            .Width(100);
        columns.Bound(c => c.Name)
            .Filterable(ftb => ftb.Cell(cell => cell.Operator("contains")))
            .Width(350);
        columns.Bound(c => c.Address)
            .Filterable(ftb => ftb.Cell(cell => cell.Operator("contains")))
            .Width(250);
        columns.Bound(c => c.City)
            .Filterable(ftb => ftb.Cell(cell => cell.Operator("contains")))
            .Width(150);
        //...
        //...

Make sure your Operators_Read action returns a JSON of IEnumerable<OperatorViewModel>.