简体   繁体   English

在 Kendo UI 中使用父网格的数据源设置子网格的数据源

[英]Set datasouce of child grid using datasource of parent grid in Kendo UI

I have this form:我有这个表格:

@*Some form fields here that accept startDate and endDate*@

<div>
    <button id="searchButton">Search</button>
</div>
<div class="col-md-12 row">
    @(Html.Kendo()
            .Grid<ProjectName.DataModels.Models.Customer>()
            .Name("CustomerGrid")
            .Columns(columns =>
            {
                columns.Bound(e => e.CustomerId);
                columns.Bound(e => e.SomeCustomerColumn);
            })
            .ClientDetailTemplateId("OrderDetails")
            .AutoBind(false) // Don't load the data yet because I'll need to supply parameters for the fetch
            .DataSource(dataSource => dataSource
                        .Ajax()
                        .Events(events=>events.Change("loadChildGrid"))
                        .PageSize(20)
                        .Model(model => model.Id("CustomerId", typeof(string)))
                        .Read(read => read.Action("GetCustomersAsync", "Customer").Data("passArguments"))
            )
    )

    <script id="OrderDetails" type="text/kendo-tmpl">
        @(Html.Kendo()
                .Grid<ProjectName.DataModels.Models.Order>()
                .Name("OrderDetails_#=CustomerId#")
                .Columns(columns =>
                {
                    columns.Bound(o => o.ProductName);
                    columns.Bound(o => o.SomeOrderColumn);
                })
                .DataSource(dataSource => dataSource
                            .Ajax()
                            .PageSize(10)
                            .Model(model=>model.Id("OrderId"))
                            .ServerOperation(false)
                )
                .AutoBind(false)
                .ToClientTemplate()
        )
    </script>
</div>
 
<script type="text/javascript">
    $("#searchButton").on("click", function () {
        // Load the customerGrid here:
        $("#CustomerGrid").data("kendoGrid").dataSource.read();
    });
    
    function passArguments() {
        var startDate = $("#startdate").data("kendoDatePicker").value();
        var endDate = $("#enddate").data("kendoDatePicker").value();
        return {
            start: startDate,
            end: endDate
        }
    }
    
    // QUESTION: How to load the child grid: OrderDetails_123 by using datasource from the parent grid?
    // THIS IS WHAT I'VE TRIED SO FAR:
    function loadChildGrid() {
        var parentData = $("#CustomerGrid").data("kendoGrid").dataSource.data();
        //Initialize the  child grid
        $.each(parentData, childDataFeeder);
    }
    
    function childDataFeeder(index, item) {
        var childGridName = "#" + "OrderDetails_" + item.CustomerId;
        var childGrid = childGridName.data("kendoGrid");
        childGrid.dataSource.data(value.Orders)
    }
</script>

And a method in the Customer controller:以及Customer controller 中的一个方法:

public async Task<ActionResult> GetCustomersAsync([DataSourceRequest] DataSourceRequest request, DateTime start, DateTime end)
{
    var customersWithOrders = GetDataForParentAndChildGrid(start, end);
    return Json(customersWithOrders.ToDataSourceResult(request));
}

private List<Customer> GetDataForParentAndChildGrid(DateTime start, DateTime end)
{
    var testData = new List<Customer>();
    // Gets required data with those dates filter and perform some mathematical calculations
    testData.Add(new Customer
    {
        CustomerId = "123",
        SomeCustomerColumn = "Blah blah",
        Orders = new List<Order>()
        {
            new Order{
                OrderId = "123ABC",
                CustomerId = "123",
                SomeOrderColumn = "Blah Blah Blah"
            }
        }
    });
    return testData;
}

My goal is to set the dataSource of child grid using data that is already available from the main grid.我的目标是使用主网格中已有的数据来设置子网格的数据源。 What I've tried so far is that I have attached Change event to the main grid which fires loadChildGrid function where I try to extract the data from main grid and pass every item of it to a childDataFeeder function to initialize the dataSource of child grid.到目前为止,我尝试将Change事件附加到触发loadChildGrid function 的主网格,我尝试从主网格中提取数据并将其中的每个项目传递给childDataFeeder function 以初始化子网格的数据源。 The issue here is that when it tries to do that, the child grid doesn't exist yet (because it's not created by Kendo until a user clicks on the expand icon in the main grid).这里的问题是,当它尝试这样做时,子网格还不存在(因为它不是由 Kendo 创建的,直到用户单击主网格中的展开图标)。

You can see what I've tried so far in the childDataFeeder method(without any success).您可以在childDataFeeder方法中看到我到目前为止所尝试的内容(没有任何成功)。 So I'd greatly appreciate your direction on this.所以我非常感谢你在这方面的指导。

Thank You!谢谢你!

After so many hours of hit and trial, I finally solved it.经过这么多小时的打击和尝试,我终于解决了它。 So I'm posting it here to save someone else's time if they come across a similar problem:因此,如果遇到类似问题,我将其发布在这里以节省其他人的时间:

I added a DetailExpand event to the main grid.我在主网格中添加了一个DetailExpand事件。 And removed the Change event on the dataSource .并删除了dataSource上的Change事件。

@(Html.Kendo()
        .Grid<ProjectName.DataModels.Models.Customer>()
        .Name("CustomerGrid")
        .Columns(columns =>
        {
            columns.Bound(e => e.CustomerId);
            columns.Bound(e => e.SomeCustomerColumn);
        })
        .ClientDetailTemplateId("OrderDetails")
        .AutoBind(false) // Don't load the data yet because I'll need to supply parameters for the fetch
        .DataSource(dataSource => dataSource
                    .Ajax()
                    .PageSize(20)
                    .Model(model => model.Id("CustomerId", typeof(string)))
                    .Read(read => read.Action("GetCustomersAsync", "Customer").Data("passArguments"))
        )
        .Events(events => events.DataBound("dataBound").DetailExpand("onExpand"))
)

Now the callback function called onExpand will be called every time we expand a row in the parent grid.现在,每次我们在父网格中展开一行时,都会调用名为onExpand的回调 function。 This is where I will now set the child grid's dataSource .这是我现在将设置子网格的dataSource的地方。

// Passing e is also important here because if you don't, this callback gets called 
// for every row in the main grid (even when you don't expand them!)
function onExpand(e) {
    var customerId = e.sender.dataItem(e.masterRow).CustomerId;
    var orders = e.sender.dataItem(e.masterRow).Orders;
    //Initialize the  child grid as well
    var childGridName = "#" + "OrderDetails_" + customerId;

    var childGrid = $(childGridName).data("kendoGrid");
    if (childGrid !== undefined) {
        childGrid.dataSource.data(orders);
    }
}

function dataBound() {
    this.expandRow(this.tbody.find("tr.k-master-row").first());
}

I used e.sender.dataItem(e.masterRow).PROPERTYNAME to access the properties that I need from the master row.我使用e.sender.dataItem(e.masterRow).PROPERTYNAME从主行访问我需要的属性。

This works flawlessly now!这现在完美无缺!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM