Hi,
I have a need to display multiple ColumnLayouts using LoadOnDemand. Currently everything is working as expecting except the Children ColumnLayouts displayed a empty Grid.
GridModel gridModel = this.GetGridModel(ajaxUpdateTarget, 0); GridUIHelper.ApplyLayout(ref gridModel, vm); gridModel.DataSource = resultSet.Result.AsQueryable(); return gridModel.GetData();Thank you
Hello Phong,
Thank you for posting in our community.
In order to address the root cause of your issue and provide you with better and more accurate support I will need an isolated working sample where the issue is reproducible. This will help me debug on my side and investigate further and find what is causing this behavior.
Additionally, a sample project illustrating Load on Demand functionality in igHierarchicalGrid could be found at the following link:
http://igniteui.com/hierarchical-grid/load-on-demand
Please have a look at this sample and if you still have any questions or concerns afterwards please fell free to get back to me with your isolated sample.
Looking forward to hearing from you.
Hello Vasya,
Thank you for getting back to me.
Yes, I did follow the Load On Demand Example.Here is what I am trying to do. Our database has over Million records. We want to take the advantage of SQL Server paging and Load On Demand, so we get the Total Count, then the first 10 records to display. Everything is working so far. However, I have a requirement to display data in Hierarchy, a Parent record would have two or more GridColumnLayoutModels.I attached the code sample. Please help
Thank you for providing me your sample.
I spent some time investigating and debugging your project further. What I noticed is that there is no Keys set for the child layout and I set them. This is important because when using GetData method for child layouts path and layout parameters should be defined in order to match the correct layout. If there is no key set for the layout it is being returned as "undefined".
GridColumnLayoutModel layout = new GridColumnLayoutModel(); layout.AutoGenerateColumns = false; layout.Key = "Histories";
GridColumnLayoutModel layout = new GridColumnLayoutModel();
layout.AutoGenerateColumns = false;
layout.Key = "Histories";
Additionally, there is no ForeignKey set for the child layout. Having ForeignKey set is essential for mapping the data for parent and child level. This is necessary in order to set the correct data for corresponding child level. I added a property in your model, in the ProductHistory class, named ProductID. This property is used to make the connection with the parent level. Since I believe this is just a sample data and in your actual data soure you have a field that could act as a foreign this is what I can recommend to ensure that the child levels are correctly loaded. For example:
public class ProductHistory { public int ProductID { get; set; } public string Something { get; set; } } . . . GridColumnLayoutModel layout = new GridColumnLayoutModel(); layout.AutoGenerateColumns = false; layout.Key = "Histories"; layout.ForeignKey = "ProductID"; layout.Columns.Add(new GridColumn() { HeaderText = "Something", Key = "Something", DataType = "string" }); layout.Columns.Add(new GridColumn() { HeaderText = "ProductID", Key = "ProductID", DataType = "number" }); layout.LoadOnDemand = false; layout.DataSourceUrl = string.Format("/Home/GetChildren?ajaxUpdateTarget={0}", "History"); layout.Width = "100%"; gridModel.ColumnLayouts.Add(layout);
public class ProductHistory
{
public int ProductID { get; set; }
public string Something { get; set; }
}
.
layout.ForeignKey = "ProductID";
layout.Columns.Add(new GridColumn() { HeaderText = "Something", Key = "Something", DataType = "string" });
layout.Columns.Add(new GridColumn() { HeaderText = "ProductID", Key = "ProductID", DataType = "number" });
layout.LoadOnDemand = false;
layout.DataSourceUrl = string.Format("/Home/GetChildren?ajaxUpdateTarget={0}", "History");
layout.Width = "100%";
gridModel.ColumnLayouts.Add(layout);
I am attaching my modified sample for your reference.
Please have a look at the provided sample and let me know if you need any further assistance with this matter.
The example that you provided is working great. However, We don't have to show the Foreign Key (ProductID) to the end user. So I attempted to remove the ProductID from the grid, then it stop working.
Can you please look into it? I am evaluating the Infragistics Product, and it's critical for me to get this working.
Thank you
In case that you have a field that you could use as a foreign key however you do not like to show in the grid you could hide it completely (even do not show it in the column chooser of Hiding feature) as following:
GridColumnLayoutModel layout = new GridColumnLayoutModel(); layout.AutoGenerateColumns = false; layout.Key = "Histories"; layout.ForeignKey = "ProductID"; layout.Columns.Add(new GridColumn() { HeaderText = "Something", Key = "Something", DataType = "string" }); layout.Columns.Add(new GridColumn() { HeaderText = "ProductID", Key = "ProductID", DataType = "number" }); layout.LoadOnDemand = false; layout.Features.Add(new GridHiding() { Inherit = true, ColumnSettings = new List<ColumnHidingSetting>() { new ColumnHidingSetting(){ColumnKey = "ProductID",AllowHiding= false, Hidden=true }} });
layout.Features.Add(new GridHiding() { Inherit = true, ColumnSettings = new List<ColumnHidingSetting>() {
new ColumnHidingSetting(){ColumnKey = "ProductID",AllowHiding= false, Hidden=true }}
});
If there is no column in your underlying data source that you could use as foreign key you could use a custom implementation of load on demand. Infragistics GetData method used to retrieve the data for child layout requires this foreign key. This means that for if you choose to use a custom approach this method could not be used. Alternative approach could be to use WrappedGridResponse to send the data for your child layouts. WrappedGridResponse is a class that wraps the response in a particular way suitable for the igHierarchicalGrid. It takes data and grid model as parameters. For example in your GetChildren method you could do the following:
public JsonResult GetChildren(string ajaxUpdateTarget, string path, string layout) { if (ajaxUpdateTarget == "History") { var histories = new List<ProductHistory>(); histories.Add(new ProductHistory() { ProductID = 0, Something = "What" }); GridModel gridModel = this.GetGridModel(ajaxUpdateTarget, 0); //gridModel.DataSource = histories.AsQueryable(); WrappedGridResponse response; response = new WrappedGridResponse(histories, null); return Json(response, JsonRequestBehavior.AllowGet); // return gridModel.GetData(path, layout); } . .
public JsonResult GetChildren(string ajaxUpdateTarget, string path, string layout)
if (ajaxUpdateTarget == "History")
var histories = new List<ProductHistory>();
histories.Add(new ProductHistory() { ProductID = 0, Something = "What" });
GridModel gridModel = this.GetGridModel(ajaxUpdateTarget, 0);
//gridModel.DataSource = histories.AsQueryable();
WrappedGridResponse response;
response = new WrappedGridResponse(histories, null);
return Json(response, JsonRequestBehavior.AllowGet);
// return gridModel.GetData(path, layout);
Please keep in mind that you will have to check the parent which is calling the method and you will have to filter the data by yourself in order to map corresponding data to its parent for each level. Additionally, GetData uses its internal techniques to handle all grid features enabled. Since every other approach is considered a custom implementation you will have to take care of how all the features are implemented manually.
I modified the provided sample with an illustration of my suggestion and I am attaching it for your reference. Please note that the data added for all child levels is the same because it has no foreign key defined and you will have your own relation to the parent and child to represent the correct data for each level.
I modified your sample
I hope you find my information helpful.
Please let me know if you need any further assistance with this matter.
This is exactly what I need for my requirement. I have another question based on this same structure/Grid setup that I will need soon. How can I get the Row of Data (Selected Data Object) and post back to the server when user click on "+" icon?
Thank you very much
Your requirement could be achieved by handling childGridCreating event. This event is fired before child grid is going to be created and allows the developer to override the child grid creation. In this event a reference to the parent row triggering the event could be retrieved. From the row you could get information about any cell that you would like and will help you uniquely identify your record. Afterwards, this data could be sent to the server(via the dataSource option) and there you could filter your data accordingly. For example:
//in Grid.cshtml $(function () { $("#grid-id-test").live("igchildgridcreating", function (evt, ui) { var parentRowId = ui.element.parents("tr[data-container='true']").prev().data("id"), parentGrid = ui.element.parents("table.ui-iggrid-table").data("igGrid"), parentRowData = parentGrid.findRecordByKey(parentRowId); //every cell value could be retrieved using the column key var productNumber = parentRowData.ProductNumber; //afterwards this value could be send to the server via dataSource option ui.options.dataSource += "&productNumber=" + productNumber; }); }); . . . //in HomeController.cs public JsonResult GetChildren(string ajaxUpdateTarget, string path, string layout, string productNumber) { if (ajaxUpdateTarget == "History" && productNumber=”AR-5381”) { //filter your data according to your productNumber and add it to the response WrappedGridResponse response; response = new WrappedGridResponse(histories, null); return Json(response, JsonRequestBehavior.AllowGet); } else { //handle it according to you scenario } }
//in Grid.cshtml
$(function () {
$("#grid-id-test").live("igchildgridcreating", function (evt, ui) {
var parentRowId = ui.element.parents("tr[data-container='true']").prev().data("id"),
parentGrid = ui.element.parents("table.ui-iggrid-table").data("igGrid"),
parentRowData = parentGrid.findRecordByKey(parentRowId);
//every cell value could be retrieved using the column key
var productNumber = parentRowData.ProductNumber;
//afterwards this value could be send to the server via dataSource option
ui.options.dataSource += "&productNumber=" + productNumber;
//in HomeController.cs
public JsonResult GetChildren(string ajaxUpdateTarget, string path, string layout, string productNumber)
if (ajaxUpdateTarget == "History" && productNumber=”AR-5381”)
//filter your data according to your productNumber and add it to the response
else
//handle it according to you scenario
I believe this approach will help you achieve your requirement. However, we have a known issue logged in our internal system regarding firing of the childGridCreating event. This issue is fixed and currently being tested.
I have created a support case with an ID of CAS-154476-Q1J6Y4 for you and I will link it to our Development issue so you will get notification when it is released. You could view this case in your account in the Support Activity page.
Thank you.
I am need have to solution ASAP.
Thanks again for looking into it.
I am currently looking into this matter for you. I will get back to you soon with more information or questions for you.
Hi Vasya,
The problem is ProductID information is not enough for me to get the Related Information of the Children. This is what I am trying to do:
1. From the expanding row, get the ProductId, ProductName, and other information. I don't want to go to the database to get the Product based on ProductId. This is not efficient because I have many nested Grids per Product.
2. Filter the Children data with (ProductId, ProductName, and other information)
3. Bind the result to the response
Please help. Thank you
I am glad that you find my suggestion helpful.
What I can suggest for achieving your requirement is using GetChildren method. This method parameters will give you enough information to determine which is the current ProductID, respectively which parent row invoked the GetChilden method. Layout parameter contains information about the current layout. Based on these two parameters you could filter your data in order to retrieve only the rows needed for the corresponding child. For example if I am trying to expand first row, Adjustable Race 0, GetChild method will be called with ajaxUpdateTarger="Histories", path: ProductID: 0,layout="Histroies". You could check which layout triggered the event and filter data accordingly and add it to the WrappedGridresponse.
public JsonResult GetChildren(string ajaxUpdateTarget, string path, string layout) { if (ajaxUpdateTarget == "History") { //filter your data according to the path and layout and add filtered data to the response WrappedGridResponse response; response = new WrappedGridResponse(histories, null); return Json(response, JsonRequestBehavior.AllowGet); } else { //filter your data according to the path and layout and add filtered data to the response gridModel.DataSource = something.AsQueryable(); WrappedGridResponse response; response = new WrappedGridResponse(something, null); return Json(response, JsonRequestBehavior.AllowGet); } }
//filter your data according to the path and layout and add filtered data to the response
gridModel.DataSource = something.AsQueryable();
response = new WrappedGridResponse(something, null);
I hope you find this information helpful.