Pregunta

Estoy usando la cuadrícula de interfaz de usuario de Kendo y actualmente muestra los registros infantiles de padres adecuadamente.Sin embargo, resulta que en realidad necesitaré mostrar los niveles de N vs. estrictamente padre-hijo.No todos los registros tendrán hijos, pero algunos tendrán múltiples niveles.

Código de cuadrícula actual:

 var jgrid = $("#boxesgrid").kendoGrid({
        columns: [
            {
                field: "JobId",
                hidden: true
            },
            {
                field: "PercentComplete",
                hidden: true
            },
            {
                field: "JobStatusId",
                hidden: true
            },
            {
                field: "AppName",
                title: "App",
                template: "<span>${AppName}</span><img class='health-img-r' id=app-${JobId} title='health' src='' alt='health_png' />",
                width: "5%",
                editable: false,
                sortable: false
            },
            {
                field: "JobName",
                title: "Box Name",
                width: "17%",
                filterable: false
            },
            {
                field: "StartTime",
                title: "Start Time",
                width: "14%",
                filterable: false
            },
            {
                field: "EndTime",
                title: "End Time",
                width: "14%",
                filterable: false
            },
            {
                field: "JobStatusId",
                title: "Status",
                template: "<img class='health-img-l' id=app-${JobId} title='health' src='' alt='health_png' /><span>${JobStatus}</span>",
                editable: false,
                filterable: false
            }
        ],
        sortable: {
            mode: "single",
            allowUnsort: true
        },
        pageable: {
            pageSizes: [50],
            numeric: true,
            refresh: true,
            pageSize: 50
        },
        autoBind: false,
        scrollable: false,
        resizable: true,
        detailInit: detailInit,
        dataSource: boxesDataSource,
        dataBound: function () {
            var grid = this;
            grid.tbody.find(">tr").each(function () {
                var row = $(this).closest("tr");
                var model = grid.dataItem(row);
                var img = $(this).find("img");
                if (model.JobStatusId == 4 && model.PercentComplete < 100) {
                    img.attr("src", function() {
                        return imgSrc + imgGreen;
                    });
                } else if (model.JobStatusId == 4) {
                    img.attr("src", function() {
                        return imgSrc + imgAmber;
                    });
                } else if (model.JobStatusId == 7) {
                    img.attr("src", function() {
                        return imgSrc + imgIce;
                    });
                } else if (model.JobStatusId == 8) {
                    img.attr("src", function() {
                        return imgSrc + imgHold;
                    });
                } else if (model.JobStatusId == 5) {
                    img.attr("src", function() {
                        return imgSrc + imgBlue;
                    });
                } else {
                    img.attr("src", function() {
                        return imgSrc + imgRed;
                    });
                }
            });
        }
    }).data("kendoGrid");

Grid actual:

function detailInit(e) {
        $("<div/>").appendTo(e.detailCell).kendoGrid({
            dataSource: {
                transport: {
                    read: {
                        url: "/api/BoxJobs"
                    },
                    parameterMap: function (data) {
                        data.parentid = e.data.JobId;
                        data.appid = e.data.AppId;
                        return kendo.stringify(data);
                    }
                },
                schema: {
                    model: { id: "JobId" }
                },
                serverPaging: true,
                serverFiltering: true,
                serverSorting: true
            },
            scrollable: false,
            sortable: true,
            columns: [
                {
                    field: "JobId",
                    hidden: true
                },
                {
                    field: "PercentComplete",
                    hidden: true
                },
                {
                    field: "JobStatusId",
                    hidden: true
                },
                {
                    field: "JobName",
                    title: "Job Name",
                    template: "<span>${JobName}</span><img class='health-img-l' id=app-${JobId} title='health' src='' alt='health_png' />",
                    width: "23%",
                    filterable: false,
                    sortable: false
                },
                {
                    field: "StartTime",
                    title: "Start Time",
                    width: "10%",
                    editable: false,
                    filterable: false,
                    sortable: false
                },
                {
                    field: "EndTime",
                    title: "End Time",
                    width: "10%",
                    editable: false,
                    filterable: false,
                    sortable: false
                },
                {
                    field: "ElapsedTime",
                    title: "Elapsed</br>Time",
                    width: "4%",
                    editable: false,
                    filterable: false,
                    sortable: false
                },
                {
                    field: "MeanRunTime",
                    title: "Mean Run</br>Time",
                    width: "3.5%",
                    editable: false,
                    filterable: false,
                    sortable: false
                },
                {
                    field: "PredecessorJobName",
                    title: "Previous Job",
                    width: "17%",
                    filterable: false,
                    sortable: false
                },
                {
                    field: "JobStatusId",
                    title: "Status",
                    template: "<img class='health-img-l' id=app-${JobId} title='health' src='' alt='health_png' /><span>${JobStatus}</span>",
                    editable: false,
                    filterable: false,
                    sortable: false
                }
            ],
            dataBound: function () {
                var grid = this;
                grid.tbody.find(">tr").each(function () {
                    var row = $(this).closest("tr");
                    var model = grid.dataItem(row);
                    var img = $(this).find("img");
                    if (model.JobStatusId == 4 && model.PercentComplete < 100) {
                        img.attr("src", function() {
                            return imgSrc + imgGreen;
                        });
                    } else if (model.JobStatusId == 4) {
                        img.attr("src", function() {
                            return imgSrc + imgAmber;
                        });
                    } else if (model.JobStatusId == 7) {
                        img.attr("src", function() {
                            return imgSrc + imgIce;
                        });
                    } else if (model.JobStatusId == 8) {
                        img.attr("src", function() {
                            return imgSrc + imgHold;
                        });
                    } else if (model.JobStatusId == 5) {
                        img.attr("src", function() {
                            return imgSrc + imgBlue;
                        });
                    } else {
                        img.attr("src", function() {
                            return imgSrc + imgRed;
                        });
                    }
                });
            }
        });
    }

Datos de nivel superior de muestra:

   {"Total":638,
"Data":[
    {"JobId":1,"AppId":1,"AppName":"APP1","LobId":2,"LobName":"LOB2","JobName":"NRS_COL_BOX","JobType":"box","TimeZone":"Chicago (Central Standard Time)","ParentJobName":null,"ParentJobId":null,"PredecessorJobName":null,"PredecessorJobId":null,"StartTime":"6/2/2014 5:00:02 PM","EndTime":"","ElapsedTime":"00:58:31","JobStatusId":4,"JobStatus":"Running","MeanRunTime":"06:57:04","PercentComplete":14.00,"TotalCount":638.0,"Children":3}
    ]
}

Datos de la muestra 2do nivel:

[
{"JobId":63,"AppId":1,"AppName":"APP1","LobId":2,"LobName":"LOB2","JobName":"NRS_COL2_BOX","JobType":"box","TimeZone":"Chicago (Central Standard Time)","ParentJobName":"NRS_COL_BOX","ParentJobId":1,"PredecessorJobName":null,"PredecessorJobId":null,"StartTime":"6/2/2014 5:00:06 PM","EndTime":"","ElapsedTime":"00:58:27","JobStatusId":4,"JobStatus":"Running","MeanRunTime":"06:57:00","PercentComplete":14.00,"TotalCount":0.0,"Children":3},
{"JobId":64,"AppId":1,"AppName":"APP1","LobId":2,"LobName":"LOB2","JobName":"NRS_COL1_BOX","JobType":"box","TimeZone":"Chicago (Central Standard Time)","ParentJobName":"NRS_COL_BOX","ParentJobId":1,"PredecessorJobName":null,"PredecessorJobId":null,"StartTime":"6/2/2014 5:00:06 PM","EndTime":"","ElapsedTime":"00:58:27","JobStatusId":4,"JobStatus":"Running","MeanRunTime":"01:42:17","PercentComplete":57.00,"TotalCount":0.0,"Children":2},
{"JobId":65,"AppId":1,"AppName":"APP1","LobId":2,"LobName":"LOB2","JobName":"NRS_COL3_BOX","JobType":"box","TimeZone":"Chicago (Central Standard Time)","ParentJobName":"NRS_COL_BOX","ParentJobId":1,"PredecessorJobName":null,"PredecessorJobId":null,"StartTime":"6/2/2014 5:00:06 PM","EndTime":"6/2/2014 5:07:42 PM","ElapsedTime":"00:07:36","JobStatusId":5,"JobStatus":"Success","MeanRunTime":"00:03:17","PercentComplete":100.0,"TotalCount":0.0,"Children":5}
]

Datos de nivel 3RD:

[
{"JobId":265,"AppId":1,"AppName":"APP1","LobId":2,"LobName":"LOB2","JobName":"NRS_COL2_S_CLEAN1","TimeZone":"Chicago (Central Standard Time)","ParentJobName":"NRS_COL2_BOX","ParentJobId":63,"PredecessorJobName":"NRS_COL2_S_TOUCH1","PredecessorJobId":266,"StartTime":"","EndTime":"","ElapsedTime":"00:58:31","JobStatusId":7,"JobStatus":"On Ice","PercentComplete":null,"Children":0},
{"JobId":266,"AppId":1,"AppName":"APP1","LobId":2,"LobName":"LOB2","JobName":"NRS_COL2_S_TOUCH1","TimeZone":"Chicago (Central Standard Time)","ParentJobName":"NRS_COL2_BOX","ParentJobId":63,"PredecessorJobName":null,"PredecessorJobId":null,"StartTime":"","EndTime":"","ElapsedTime":"00:58:31","JobStatusId":7,"JobStatus":"On Ice","PercentComplete":null,"Children":0},
{"JobId":267,"AppId":1,"AppName":"APP1","LobId":2,"LobName":"LOB2","JobName":"NRS_COL2_A_ZFINSNAMA","TimeZone":"Chicago (Central Standard Time)","ParentJobName":"NRS_COL2_BOX","ParentJobId":63,"PredecessorJobName":"NRS_COL2_S_CLEAN1","PredecessorJobId":265,"StartTime":"6/2/2014 5:02:02 PM","EndTime":"","ElapsedTime":"00:58:31","JobStatusId":4,"JobStatus":"Running","PercentComplete":null,"Children":0}
]

No tengo ningún problema con la jerarquía tradicional de padres y niños, pero estoy luchando con la lucha de cómo voy a hacer que la plantilla detalla se comporte para sus hijos.

Me gustaría que la plantilla sea apropiada para la visualización de niños / nietos, sin indicador desplegable si no tiene hijos adicionales.Supongo que puedo evaluar los datos de DioBound, pero no estoy viendo cómo hacerlo.

¿Fue útil?

Solución

Tomó un tiempo, pero finalmente trabajé una respuesta con alguna guía de los PEEPS en Telerik. Solo estaba teniendo el tiempo más difícil de conseguir mi cabeza alrededor de la solución.

Vladimir (en Telerik) sugirió que utilice una llamada AJAX personalizada en la función de detalleIniting usando una función en el éxito para determinar si tenía datos infantiles a considerar. Como necesitaba la rejilla detallada, sin importar qué, moví el cheque de niño en otra función que crea la cuadrícula de detalles. Si encuentro datos infantiles, agrego un parámetro de detalle para la nueva cuadrícula. Si no, simplemente rindo la nueva cuadrícula de detalles.

La función AJAX INITDETAIL:

function detailInit(e) {
            var eventData = e;
            $.ajax({
                url: apiUrl + "ProcessJobs",
                type: "POST",
                data: {BoxId: e.data.JobId, AppId: e.data.AppId}, 
                dataType: "json",
                success: function(data, status, xhr) {
                    initializeDetailGrid(eventData, data);
                }
            }

La función para construir la nueva cuadrícula de detalles con el cheque para los niños:

function initializeDetailGrid(e, result) {
            var moreChildren = result[0].HasChildren;
            var gridBaseOptions = {
                dataSource: result,
                scrollable: false,
                sortable: true,
                columns: [
                    {
                        field: "ParentJobId",
                        title: "Parent Job"
                    },
                    {
                        field: "JobId",
                        title: "Job Id"
                    },
                    {
                        field: "JobName",
                        title: "Job Name",
                    },
                    {
                        field: "JobStatus",
                        title: "Status"
                    },
                    {
                        field: "JobStatusId",
                        title: "Status Code"
                    },
                    {
                        field: "HasChildren",
                        title: "Has Children"
                    },
                    {
                        field: "ChildrenCount",
                        title: "Child Jobs"
                    }
                ]
            };

            var gridOptions = {};
            if (moreChildren) {
                gridOptions = $.extend({}, gridBaseOptions, { detailInit: detailInit });
            } else {
                gridOptions = gridBaseOptions;
            };
            $("<div/>").appendTo(e.detailCell).kendoGrid(gridOptions);
        };

Para completar, aquí está la página completa y los datos de ejemplo del proyecto de muestra. Es un sitio web basado en .NET MVC4, utilizando los servicios de API web para datos y Kendo UI para el cliente.

Aquí está el código de la página:

@{
    ViewBag.Title = "n-level Grid";
}

<script type="text/javascript">
    $(document).ready(function () {
        var isParent, appId, lobId, boxId;
        var apiUrl = '@ViewBag.ApiUrl';

        var lobDataSource = new kendo.data.DataSource({
            transport: {
                read: {
                    url: apiUrl + "Lob"
                }
            },
            schema: {
                model: {
                    id: "LobId",
                    hasChildren: "HasChildren"
                }
            }
        });

        var appsDataSource = new kendo.data.DataSource({
            transport: {
                read: {
                    url: apiUrl + "App"
                },
                parameterMap: function (data, action) {
                    if (action === "read") {
                        data.lobid = lobId;
                        data.parent = isParent;
                        return data;
                    } else {
                        return data;
                    }
                }
            }
        });

        var filterDataSource = new kendo.data.DataSource({
            transport: {
                read: {
                    url: apiUrl + "Theme"
                }
            },
            schema: {
                model: { id: "FilterId" }
            }
        });

        var boxesDataSource = new kendo.data.DataSource({
            transport: {
                read: {
                    url: apiUrl + "Process"
                },
                parameterMap: function (data) {
                    data.appid = appId;
                    data.parent = isParent;
                    data.lobid = lobId;
                    return kendo.stringify(data);
                }
            },
            schema: {
                data: "Data",
                total: "Total",
                model: { id: "JobId" }
            },
            serverPaging: true,
            serverFiltering: true,
            serverSorting: true
        });

        var lobnav = $("#lobnav").kendoTreeView({
            select: function (e) {
                var tree = this;
                var src = tree.dataItem(e.node);
                lobId = src.LobId;
                isParent = src.HasChildren;
            },
            change: function (e) {
                appsDataSource.read();
            },
            dataSource: {
                transport: {
                    read: {
                        url: apiUrl + "Lob"
                    }
                },
                schema: {
                    model: {
                        id: "LobId",
                        hasChildren: "HasChildren"
                    }
                }
            },
            loadOnDemand: false,
            dataTextField: "LobName"
        });

        var appnav = $("#lobapp").kendoListView({
            selectable: "single",
            autoBind: false,
            change: function () {
                var idx = this.select().index();
                var itm = this.dataSource.view()[idx];
                appId = itm.AppId;
                boxesDataSource.query({
                    page: 1,
                    pageSize: 10
                });
            },
            template: "<div class='pointercursor'>${AppName}</div>",
            dataSource: appsDataSource
        });

        var jobsfilter = $("#jobfilter").kendoListView({
            selectable: "single",
            loadOnDemand: false,
            template: "<div class='pointercursor' id=${FilterId}>${FilterName}</div>",
            dataSource: filterDataSource,
            dataBound: function () {
                var dsource = $("#jobfilter").data("kendoListView").dataSource;
                if (dsource.at(0).FilterName !== "All") {
                    dsource.insert(0, { FilterId: 0, FilterName: "All" });
                }
            },
            change: function () {
                var itm = this.select().index(), dataItem = this.dataSource.view()[itm];
                var appDs = appsDataSource.view(), apps = $("#lobapp").data("kendoListView"),
                    selected = $.map(apps.select(), function (item) {
                        return appDs[$(item).index()].AppName;
                    });
                if (selected.length > 0) {
                    if (dataItem.FilterId !== 0) {
                        var $filter = new Array();
                        $filter.push({ field: "JobStatusId", operator: "eq", value: dataItem.FilterId });
                        jgrid.dataSource.filter($filter);
                    } else {
                        jgrid.dataSource.filter({});
                    }
                }
            }
        });

        var jgrid = $("#boxesgrid").kendoGrid({
            columns: [
                {
                    field: "AppName",
                    title: "App"
                },
                {
                    field: "JobId",
                    title: "Job Id"
                },
                {
                    field: "JobName",
                    title: "Job Name",
                },
                {
                    field: "JobStatus",
                    title: "Status"
                },
                {
                    field: "JobStatusId",
                    title: "Status Code"
                },
                {
                    field: "HasChildren",
                    title: "Has Children"
                },
                {
                    field: "ChildrenCount",
                    title: "Child Jobs"
                }
            ],
            sortable: {
                mode: "single",
                allowUnsort: true
            },
            pageable: {
                pageSizes: [10],
                numeric: true,
                refresh: true,
                pageSize: 10
            },
            autoBind: false,
            scrollable: false,
            resizable: true,
            detailInit: detailInit,
            dataSource: boxesDataSource
        }).data("kendoGrid");

        function detailInit(e) {
            var eventData = e;
            $.ajax({
                url: apiUrl + "ProcessJobs",
                type: "POST",
                data: {BoxId: e.data.JobId, AppId: e.data.AppId}, 
                dataType: "json",
                success: function(data, status, xhr) {
                    initializeDetailGrid(eventData, data);
                }
            });
        };

        function initializeDetailGrid(e, result) {
            var moreChildren = result[0].HasChildren;
            var gridBaseOptions = {
                dataSource: result,
                scrollable: false,
                sortable: true,
                columns: [
                    {
                        field: "ParentJobId",
                        title: "Parent Job"
                    },
                    {
                        field: "JobId",
                        title: "Job Id"
                    },
                    {
                        field: "JobName",
                        title: "Job Name",
                    },
                    {
                        field: "JobStatus",
                        title: "Status"
                    },
                    {
                        field: "JobStatusId",
                        title: "Status Code"
                    },
                    {
                        field: "HasChildren",
                        title: "Has Children"
                    },
                    {
                        field: "ChildrenCount",
                        title: "Child Jobs"
                    }
                ]
            };

            var gridOptions = {};
            if (moreChildren) {
                gridOptions = $.extend({}, gridBaseOptions, { detailInit: detailInit });
            } else {
                gridOptions = gridBaseOptions;
            };
            $("<div/>").appendTo(e.detailCell).kendoGrid(gridOptions);
        };
    });
</script>

<div class="col-md-2">
    <div class="panel panel-default">
        <div class="panel-heading">Line of Business</div>
        <div class="panel-body" id="lobnav"></div>
    </div>
    <div class="panel panel-default">
        <div class="panel-heading">Application</div>
        <div class="panel-body" id="lobapp"></div>
    </div>
    <div class="panel panel-default">
        <div class="panel-heading">Filter</div>
        <div class="panel-body" id="jobfilter">
        </div>
    </div>
</div>
<div class="col-md-10">
    <div id="boxesgrid"></div>
</div>

Los datos son realmente impresos para esta aplicación de muestra, pero todavía lo devuelvo a través de la API web. Aquí hay una muestra de los datos de nivel más alto:

new Process {JobId = 108, AppId = 1, AppName = "App1", LobId = 2, LobName = "Lob2", JobName = "job_108", ParentJobName = null, ParentJobId = null, JobStatusId = 4, JobStatus = "Running", ChildrenCount = 3, HasChildren = true},
new Process {JobId = 109, AppId = 1, AppName = "App1", LobId = 2, LobName = "Lob2", JobName = "job_109", ParentJobName = null, ParentJobId = null, JobStatusId = 5, JobStatus = "Success", ChildrenCount = 4, HasChildren = true},
new Process {JobId = 110, AppId = 1, AppName = "App1", LobId = 2, LobName = "Lob2", JobName = "job_110", ParentJobName = null, ParentJobId = null, JobStatusId = 4, JobStatus = "Running", ChildrenCount = 2, HasChildren = true},
new Process {JobId = 111, AppId = 1, AppName = "App1", LobId = 2, LobName = "Lob2", JobName = "job_111", ParentJobName = null, ParentJobId = null, JobStatusId = 5, JobStatus = "Success", ChildrenCount = 5, HasChildren = true},

Aquí hay algunos datos de segundo nivel (datos infantiles):

new Process {JobId = 1037, AppId = 1, AppName = "App1", LobId = 2, LobName = "Lob2", JobName = "job_1037", ParentJobName = "job_109", ParentJobId = 109, JobStatusId = 4, JobStatus = "Running", ChildrenCount = 0, HasChildren = false},
new Process {JobId = 1038, AppId = 1, AppName = "App1", LobId = 2, LobName = "Lob2", JobName = "job_1038", ParentJobName = "job_109", ParentJobId = 109, JobStatusId = 4, JobStatus = "Running", ChildrenCount = 0, HasChildren = false},
new Process {JobId = 1039, AppId = 1, AppName = "App1", LobId = 2, LobName = "Lob2", JobName = "job_1039", ParentJobName = "job_110", ParentJobId = 110, JobStatusId = 4, JobStatus = "Running", ChildrenCount = 2, HasChildren = true},
new Process {JobId = 1040, AppId = 1, AppName = "App1", LobId = 2, LobName = "Lob2", JobName = "job_1040", ParentJobName = "job_110", ParentJobId = 110, JobStatusId = 4, JobStatus = "Running", ChildrenCount = 2, HasChildren = true},

Algunos de los datos de tercer nivel (nietos):

new Process {JobId = 5000, AppId = 1, AppName = "App1", LobId = 2, LobName = "Lob2", JobName = "job_5000", ParentJobName = "job_1039", ParentJobId = 1039, JobStatusId = 5, JobStatus = "Success", ChildrenCount = 0, HasChildren = false},
new Process {JobId = 5001, AppId = 1, AppName = "App1", LobId = 2, LobName = "Lob2", JobName = "job_5001", ParentJobName = "job_1039", ParentJobId = 1039, JobStatusId = 5, JobStatus = "Success", ChildrenCount = 0, HasChildren = false},
new Process {JobId = 5002, AppId = 1, AppName = "App1", LobId = 2, LobName = "Lob2", JobName = "job_5002", ParentJobName = "job_1040", ParentJobId = 1040, JobStatusId = 5, JobStatus = "Success", ChildrenCount = 0, HasChildren = false},
new Process {JobId = 5003, AppId = 1, AppName = "App1", LobId = 2, LobName = "Lob2", JobName = "job_5003", ParentJobName = "job_1040", ParentJobId = 1040, JobStatusId = 5, JobStatus = "Success", ChildrenCount = 0, HasChildren = false},
new Process {JobId = 5004, AppId = 1, AppName = "App1", LobId = 2, LobName = "Lob2", JobName = "job_5004", ParentJobName = "job_1041", ParentJobId = 1041, JobStatusId = 5, JobStatus = "Success", ChildrenCount = 1, HasChildren = true},

y así sucesivamente ...

Está funcionando correctamente por 4 niveles en mis pruebas. Hay problemas de formato con las múltiples cuadrículas anidadas que estaré abordando.

Otros consejos

No estoy seguro de si esta pregunta aún está abierta, pero una solución simple es usar la recursión en la función "detalle", como a continuación:

<!DOCTYPE html>
<html>
<head>
    <base href="https://demos.telerik.com/kendo-ui/grid/hierarchy">
    <style>html { font-size: 14px; font-family: Arial, Helvetica, sans-serif; }</style>
    <title></title>
    <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.117/styles/kendo.common-material.min.css" />
    <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.117/styles/kendo.material.min.css" />
    <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.117/styles/kendo.material.mobile.min.css" />

    <script src="https://kendo.cdn.telerik.com/2018.1.117/js/jquery.min.js"></script>
    <script src="https://kendo.cdn.telerik.com/2018.1.117/js/kendo.all.min.js"></script>
    

</head>
<body>

        <div id="example">
            <div id="grid"></div>          
            <script>

var myData = [{ item: 0, title:"Meat" , items:[
                { item: 0.1, title:"Beef"},
                { item: 0.2, title:"Chicken"},
              ]}, 
              { item: 1, title:"Vegetables", items:[
                { item: 1.0, title:"Carrot"},
                { item: 1.1, title:"Pies", items:[
                  { item: 1.11, title:"Pie1"},
                  { item: 1.12, title:"Pie2"},
                  { item: 1.13, title:"Pie3"}
                 ]},
              ]}
             ];
              
                $(document).ready(function() {
                    var element = $("#grid").kendoGrid({
                        dataSource: {
                            data: myData
                        },
                        height: 600,
                        sortable: true,
                        pageable: true,
                        detailInit: detailInit1,
                        dataBound: function() {
                            this.expandRow(this.tbody.find("tr.k-master-row").last());
                        },
                        columns: [
                            {
                                field: "item",
                                title: "ID",
                                width: "110px"
                            },
                            {
                                field: "title",
                                title: "Food",
                                width: "110px"
                            }
                        ]
                    });
                });

                function detailInit1(e) {                  
                    $("<div/>").appendTo(e.detailCell).kendoGrid({
                        dataSource: {
                            data: e.data.items  //data is the current position item, items is its child items
                        },
                        scrollable: false,
                        sortable: true,
                        pageable: true,   
                        detailInit: detailInit1,
                        dataBound: function() {
                            this.expandRow(this.tbody.find("tr.k-master-row").last());
                        },
                        columns: [
                            {
                                field: "item",
                                title: "ID",
                                width: "110px"
                            },
                            {
                                field: "title",
                                title: "Food",
                                width: "110px"
                            }
                        ]
                    });
                }
              
            </script>
        </div>


</body>
</html>

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top