I am dynamically adding columns to a grid because I don't know the names of all the columns until runtime. That worked great until I needed to turn on filtering. There will be four preset views that will filter the data rows, showing and hiding rows based on the definition of the filter, which I do know at design time.
Here's the definition of the grid:
$(function () { // Define the grid $("#mainGrid_@Model.GridIndex").igGrid({ autoGenerateColumns: false, width: "100%", dataSource: new Array(0), // Just use an empty array to define the dataSource for now. We will populate it with data later dataSourceType: "json", scrolling: true, columns: [ { headerText: "", key: "RowType", dataType: "numeric", hidden: true }, { headerText: "", key: "RowFormat", dataType: "numeric", hidden: true }, { headerText: "", key: "Oversold", width: "25px", dataType: "string" }, { headerText: "", key: "Status", width: "25px", dataType: "string" }, { headerText: "", key: "OrderNumberInfo", width: "100px", dataType: "string" }, { headerText: "", key: "GeneralDescription", width: "200px", dataType: "string" }, { headerText: "", key: "RowDate", width: "150px", dataType: "string" }, { headerText: "", key: "RowDateFormat", dataType: "numeric", hidden: true }, { headerText: "", key: "MultiIndicator", width: "20px", dataType: "string" }, { headerText: "", key: "FobOrTransfer", width: "100px", dataType: "string" }, { headerText: "Pkg", key: "PackageSize", width: "75px", dataType: "string" }, { headerText: "Brd Ft", key: "BoardFeet", width: "90px", dataType: "numeric", format: "###,###,###" } ], features: [ { name: "Filtering", type: "local", mode: "simple", filterSummaryAlwaysVisible: false, renderFilterButton: false, columnSettings: [ { columnKey: "RowFormat", allowFiltering: false }, { columnKey: "Oversold", allowFiltering: false }, { columnKey: "Status", allowFiltering: false }, { columnKey: "OrderNumberInfo", allowFiltering: false }, { columnKey: "GeneralDescription", allowFiltering: false }, { columnKey: "RowDate", allowFiltering: false }, { columnKey: "RowDateFormat", allowFiltering: false }, { columnKey: "MultiIndicator", allowFiltering: false }, { columnKey: "FobOrTransfer", allowFiltering: false }, { columnKey: "PackageSize", allowFiltering: false }, { columnKey: "BoardFeet", allowFiltering: false } ] } ], rowsRendered: function() { FormatGrid('@Model.GridIndex', @Html.Raw(Json.Encode(Model.LengthValues))); } }); // Add the length value columns to the grid. The AddLengthColumns function is in the main page AddLengthColumns('@Model.GridIndex', @Html.Raw(Json.Encode(Model.LengthValues))); // Get the data for the grid. The GetData function is in the main page GetData('@Model.GridIndex', @Html.Raw(Json.Encode(Model))); }); // End onLoad
The functions that add the dynamic columns and perform other duties are here:
function GetData(gridIndex, matrixLayout) { $.ajax({ type: "POST", url: '@Url.Action("GetDataForTable", "Home")', data: matrixLayout, dataType: "json" // we are expecting JSON data back }) .done( function(json) { $("#mainGrid_" + gridIndex).igGrid("option", "dataSource", json); $("#mainGrid_" + gridIndex).igGrid("dataBind"); }) .fail( function(jqXhr, textStatus, errorThrown) { console.warn(jqXhr.responseText); alert(errorThrown + ' getJSON request failed for grid ' + gridIndex, textStatus); }) .always( function() { } ); } function AddLengthColumns(gridIndex, columnList) { // Get var cols = $("#mainGrid_" + gridIndex).igGrid("option", "columns"); // Set - Iterate through the columnList and add new columns for each length value in the list $.each(columnList, function(index, item) { var newColumn = { headerText: item, key: FixLengthHeaderColumnNames(item), width: "75px", dataType: "number", format: "###,###,###" }; cols.push(newColumn); // This is how we signal when a column is oversold var oversoldColumn = { headerText: "", key: "Oversold" + FixLengthHeaderColumnNames(item), width: '0px', dataType: 'bool' } cols.push(oversoldColumn); } ); // Finish $("#mainGrid_" + gridIndex).igGrid("option", "columns", cols); // Now set the filtering for all those new columns to false var colSettings = $("#mainGrid_" + gridIndex).igGridFiltering("option", "columnSettings"); $.each(columnList, function (index, lengthColumnName){ var filterColumn = FixLengthHeaderColumnNames(lengthColumnName); var oversoldFilterColumn = "Oversold" + FixLengthHeaderColumnNames(lengthColumnName); for (var i = 0; i < colSettings.length; i++) { if (colSettings[i].columnKey === filterColumn || colSettings[i].columnKey === oversoldFilterColumn) { colSettings[i].allowFiltering = false; } } }); $("#mainGrid_" + gridIndex).igGridFiltering("option", "columnSettings", colSettings); } function FixLengthHeaderColumnNames(columnName) { return columnName.replace(/[^a-z,A-Z0-9_]/g, '_'); } function FormatGrid(gridIndex, dynamicColumnList) { var gridSelector = "#mainGrid_" + gridIndex; // Contains all the rows for this grid var rows = $(gridSelector).igGrid("rows"); if (rows.length === 0) return; // This happens on the first bind to an empty array, we need to ignore that binding $.each(rows, function(rowIndex, row) { try { var rowBold = $(gridSelector).igGrid("getCellValue", rowIndex, "RowFormat"); if (rowBold !== null && rowBold === 1 || rowBold === '1') { $(row).addClass("rowBoldFormat"); } } catch (e) { console.error("Error trying to bold row " + "Row = " + rowIndex + " " + e); } try { // Date Red/Green formatting var dateFormat = $(gridSelector).igGrid("getCellValue", rowIndex, "RowDateFormat"); if (dateFormat !== null && dateFormat !== undefined) { var dateCellIndex = $(gridSelector).igGrid("getVisibleIndexByKey", "RowDate"); var dateCell = $(gridSelector).igGrid("cellAt", rowIndex, dateCellIndex); if (dateCell !== null && dateCell !== undefined) { if (dateFormat === 1) { $(dateCell).addClass("dateDisplayGreen"); } // 2 is red else if (dateFormat === 2) { $(dateCell).addClass("dateDisplayRed"); } } } } catch (e1) { console.error("Error trying to format Date. " + e1); } $.each(dynamicColumnList, function(columnIndex, dynamicColumn) { try { var oversoldCell = $(gridSelector).igGrid("getCellValue", rowIndex, "Oversold" + dynamicColumn); if (oversoldCell !== null && oversoldCell !== undefined && oversoldCell === true) { var lengthCellIndex = $(gridSelector).igGrid("getVisibleIndexByKey", dynamicColumn); var lengthCell = $(gridSelector).igGrid("cellAt", lengthCellIndex, rowIndex); $(lengthCell).addClass("overSoldHighlight"); var orderCellIndex = $(gridSelector).igGrid("getVisibleIndexByKey", "OrderNumberInfo"); var orderCell = $(gridSelector).igGrid("cellAt", orderCellIndex, rowIndex); $(orderCell).addClass("overSoldHighlight"); var generalDescriptionCellIndex = $(gridSelector).igGrid("getVisibleIndexByKey", "GeneralDescription"); var generalDescriptionCell = $(gridSelector).igGrid("cellAt", generalDescriptionCellIndex, rowIndex); $(generalDescriptionCell).addClass("overSoldHighlight"); var rowDateCellIndex = $(gridSelector).igGrid("getVisibleIndexByKey", "RowDate"); var rowDateCell = $(gridSelector).igGrid("cellAt", rowDateCellIndex, rowIndex); $(rowDateCell).addClass("overSoldHighlight"); var multiIndicatorCellIndex = $(gridSelector).igGrid("getVisibleIndexByKey", "MultiIndicator"); var multiIndicatorCell = $(gridSelector).igGrid("cellAt", multiIndicatorCellIndex, rowIndex); $(multiIndicatorCell).addClass("overSoldHighlight"); } } catch (e2) { console.error("Highlight error for Grid = " + gridSelector + ". Column = Oversold" + dynamicColumn + ". Row = " + rowIndex + ". Error = " + e2); } }); }); } function SwitchView(viewName) { // loop through each of the grid layouts and set the filter to display the proper view var layoutCount = @Model.Layouts.Count; switch (viewName) { case "ForecastByProduct": $("#title").html("Production Forecast Detail"); $("#productionForecastDetailRow").removeClass("displayInline").addClass("displayHidden"); $("#productionForecastSummaryRow").removeClass("displayHidden").addClass("displayInline"); $("#weekOfProductionSummaryRow").removeClass("displayHidden").addClass("displayInline"); $("#vmiProductionDetailRow").removeClass("displayHidden").addClass("displayInline"); break; case "ForecastByProduction": $("#title").html("Production Forecast Summary"); $("#productionForecastDetailRow").removeClass("displayHidden").addClass("displayInline"); $("#productionForecastSummaryRow").removeClass("displayInline").addClass("displayHidden"); $("#weekOfProductionSummaryRow").removeClass("displayHidden").addClass("displayInline"); $("#vmiProductionDetailRow").removeClass("displayHidden").addClass("displayInline"); break; case "ForecastVmi": $("#title").html("VMI Production Forecast Detail"); $("#productionForecastDetailRow").removeClass("displayInline").addClass("displayHidden"); $("#productionForecastSummaryRow").removeClass("displayHidden").addClass("displayInline"); $("#weekOfProductionSummaryRow").removeClass("displayHidden").addClass("displayInline"); $("#vmiProductionDetailRow").removeClass("displayInline").addClass("displayHidden"); break; case "ForecastWeekOf": $("#title").html("Week Of Production Forecast Summary"); $("#productionForecastDetailRow").removeClass("displayInline").addClass("displayHidden"); $("#productionForecastSummaryRow").removeClass("displayHidden").addClass("displayInline"); $("#weekOfProductionSummaryRow").removeClass("displayInline").addClass("displayHidden"); $("#vmiProductionDetailRow").removeClass("displayHidden").addClass("displayInline"); break; } for (var i = 0; i < layoutCount; i++) { SwitchGridView(viewName, i.toString()); } return false; } function SwitchGridView(viewName, gridIndex) { var filters = []; switch(viewName) { case "ForecastByProduct": filters = [ { fieldName: "RowType", expr: 10, cond: "equals", logic: "OR" }, // On Hand Inventory { fieldName: "RowType", expr: 20, cond: "equals", logic: "OR" }, // Order Info { fieldName: "RowType", expr: 30, cond: "equals", logic: "OR" }, // Available to Ship Inventory { fieldName: "RowType", expr: 40, cond: "equals", logic: "OR" }, // Production { fieldName: "RowType", expr: 50, cond: "equals", logic: "OR" }, // Picked / Ready { fieldName: "RowType", expr: 60, cond: "equals", logic: "OR" }, // Picked / Ready Summary { fieldName: "RowType", expr: 70, cond: "equals", logic: "OR" }, // Purchase Order { fieldName: "RowType", expr: 80, cond: "equals", logic: "OR" } // Inbound Transfer ]; break; case "ForecastByProduction": filters = [ { fieldName: "RowType", expr: 10, cond: "equals", logic: "OR" }, // On Hand Inventory //{ fieldName: "RowType", expr: 20, cond: "equals", logic: "OR" }, // Order Info { fieldName: "RowType", expr: 30, cond: "equals", logic: "OR" }, // Available to Ship Inventory { fieldName: "RowType", expr: 40, cond: "equals", logic: "OR" } // Production //{ fieldName: "RowType", expr: 50, cond: "equals", logic: "OR" }, // Picked / Ready //{ fieldName: "RowType", expr: 60, cond: "equals", logic: "OR" }, // Picked / Ready Summary //{ fieldName: "RowType", expr: 70, cond: "equals", logic: "OR" }, // Purchase Order //{ fieldName: "RowType", expr: 80, cond: "equals", logic: "OR" } // Inbound Transfer ]; break; case "ForecastVmi": filters = [ { fieldName: "RowType", expr: 10, cond: "equals", logic: "OR" }, // On Hand Inventory { fieldName: "RowType", expr: 20, cond: "equals", logic: "OR" }, // Order Info { fieldName: "RowType", expr: 30, cond: "equals", logic: "OR" }, // Available to Ship Inventory { fieldName: "RowType", expr: 40, cond: "equals", logic: "OR" } // Production //{ fieldName: "RowType", expr: 50, cond: "equals", logic: "OR" }, // Picked / Ready //{ fieldName: "RowType", expr: 60, cond: "equals", logic: "OR" }, // Picked / Ready Summary //{ fieldName: "RowType", expr: 70, cond: "equals", logic: "OR" }, // Purchase Order //{ fieldName: "RowType", expr: 80, cond: "equals", logic: "OR" } // Inbound Transfer ]; break; case "ForecastWeekOf": filters = [ { fieldName: "RowType", expr: 10, cond: "equals", logic: "OR" }, // On Hand Inventory //{ fieldName: "RowType", expr: 20, cond: "equals", logic: "OR" }, // Order Info { fieldName: "RowType", expr: 30, cond: "equals", logic: "OR" }, // Available to Ship Inventory { fieldName: "RowType", expr: 40, cond: "equals", logic: "OR" } // Production //{ fieldName: "RowType", expr: 50, cond: "equals", logic: "OR" }, // Picked / Ready //{ fieldName: "RowType", expr: 60, cond: "equals", logic: "OR" }, // Picked / Ready Summary //{ fieldName: "RowType", expr: 70, cond: "equals", logic: "OR" }, // Purchase Order //{ fieldName: "RowType", expr: 80, cond: "equals", logic: "OR" } // Inbound Transfer ]; break; } $("mainGrid_" + gridIndex).igGridFiltering("filter", filters); }
The problems I'm running into currently are these.
BTW - I am making the ajax call and getting a JSON return for the data, but the data is not showing up in the grid.
What am I doing wrong?
Oh my goodness. I'm so embarrassed. Thank you.
Hello Kenneth,
If you are referring to the calls to the Filtering API not working, this is because the selector you were using didn't have the # sign to indicate a search by ID. I updated the fiddle and now switching between views changes the filtering applied to the grids: https://jsfiddle.net/b7c820vq/
The filtering editors don't show because their allowFiltering column setting is set to false, but I assumed this is indended.
I hope this helps! Let me know if you have any other issues or concerns!
Best regards,
Stamen Stoychev
I've created a fiddle that encapsulates my code and behaves the same way.
I don't see issues with the code, it all seems fine. I can't be sure, why the filters are not applying. I updated the fiddle to check how the filter API behaves and it works as expected.
Are you re-creating those grids after switching the views or something like that which will result in removing the filtering?
Can you isolate your scenario into the fiddle?
I'm actually not changing the data sources, so just updating the filters is what I want. That's where I started, but it wasn't working, so I switched gears.
I have a RowType field that is a number that is a hidden field. When someone clicks on a link to switch views it calls a JavaScript function called SwitchView with the name of the view.
function SwitchView(viewName) { // loop through each of the grid layouts and set the filter to display the proper view var layoutCount = @Model.Layouts.Count; switch (viewName) { case "ForecastByProduct": $("#title").html("Production Forecast Detail"); $("#productionForecastDetailRow").removeClass("displayInline").addClass("displayHidden"); $("#productionForecastSummaryRow").removeClass("displayHidden").addClass("displayInline"); $("#weekOfProductionSummaryRow").removeClass("displayHidden").addClass("displayInline"); $("#vmiProductionDetailRow").removeClass("displayHidden").addClass("displayInline"); break; case "ForecastByProduction": $("#title").html("Production Forecast Summary"); $("#productionForecastDetailRow").removeClass("displayHidden").addClass("displayInline"); $("#productionForecastSummaryRow").removeClass("displayInline").addClass("displayHidden"); $("#weekOfProductionSummaryRow").removeClass("displayHidden").addClass("displayInline"); $("#vmiProductionDetailRow").removeClass("displayHidden").addClass("displayInline"); break; case "ForecastVmi": $("#title").html("VMI Production Forecast Detail"); $("#productionForecastDetailRow").removeClass("displayHidden").addClass("displayInline"); $("#productionForecastSummaryRow").removeClass("displayHidden").addClass("displayInline"); $("#weekOfProductionSummaryRow").removeClass("displayHidden").addClass("displayInline"); $("#vmiProductionDetailRow").removeClass("displayInline").addClass("displayHidden"); break; case "ForecastWeekOf": $("#title").html("Week Of Production Forecast Summary"); $("#productionForecastDetailRow").removeClass("displayHidden").addClass("displayInline"); $("#productionForecastSummaryRow").removeClass("displayHidden").addClass("displayInline"); $("#weekOfProductionSummaryRow").removeClass("displayInline").addClass("displayHidden"); $("#vmiProductionDetailRow").removeClass("displayHidden").addClass("displayInline"); break; } var filters = GetGridFilter(viewName); for (var i = 0; i < layoutCount; i++) { $("mainGrid_" + i).igGridFiltering("filter", filters, true); // apply the filter and update the UI } return false; }
function GetGridFilter(viewName) { var filters = []; switch (viewName) { case "ForecastByProduct": filters = [ { fieldName: "RowType", expr: 10, cond: "equals", logic: "OR" }, // On Hand Inventory { fieldName: "RowType", expr: 20, cond: "equals", logic: "OR" }, // Order Info { fieldName: "RowType", expr: 30, cond: "equals", logic: "OR" }, // Available to Ship Inventory { fieldName: "RowType", expr: 40, cond: "equals", logic: "OR" }, // Production { fieldName: "RowType", expr: 50, cond: "equals", logic: "OR" }, // Picked / Ready { fieldName: "RowType", expr: 60, cond: "equals", logic: "OR" }, // Picked / Ready Summary { fieldName: "RowType", expr: 70, cond: "equals", logic: "OR" }, // Purchase Order { fieldName: "RowType", expr: 80, cond: "equals", logic: "OR" } // Inbound Transfer ]; break; case "ForecastByProduction": filters = [ { fieldName: "RowType", expr: 10, cond: "equals", logic: "OR" }, // On Hand Inventory { fieldName: "RowType", expr: 30, cond: "equals", logic: "OR" }, // Available to Ship Inventory { fieldName: "RowType", expr: 50, cond: "equals", logic: "OR" } // Picked / Ready //{ fieldName: "RowType", expr: 40, cond: "doesNotEqual" }, // Production //{ fieldName: "RowType", expr: 20, cond: "doesNotEqual" }, // Order Info //{ fieldName: "RowType", expr: 60, cond: "doesNotEqual" }, // Picked / Ready Summary //{ fieldName: "RowType", expr: 70, cond: "doesNotEqual" }, // Purchase Order //{ fieldName: "RowType", expr: 80, cond: "doesNotEqual" } // Inbound Transfer ]; break; case "ForecastVmi": // This rolls up all the similar products together, the raw data will need to be modified filters = [ { fieldName: "RowType", expr: 10, cond: "equals", logic: "OR" }, // On Hand Inventory { fieldName: "RowType", expr: 20, cond: "equals", logic: "OR" }, // Order Info { fieldName: "RowType", expr: 30, cond: "equals", logic: "OR" }, // Available to Ship Inventory { fieldName: "RowType", expr: 40, cond: "equals", logic: "OR" } // Production //{ fieldName: "RowType", expr: 50, cond: "doesNotEqual" }, // Picked / Ready //{ fieldName: "RowType", expr: 60, cond: "doesNotEqual" }, // Picked / Ready Summary //{ fieldName: "RowType", expr: 70, cond: "doesNotEqual" }, // Purchase Order //{ fieldName: "RowType", expr: 80, cond: "doesNotEqual" } // Inbound Transfer ]; break; case "ForecastWeekOf": filters = [ { fieldName: "RowType", expr: 10, cond: "equals", logic: "OR" }, // On Hand Inventory { fieldName: "RowType", expr: 30, cond: "equals", logic: "OR" }, // Available to Ship Inventory { fieldName: "RowType", expr: 40, cond: "equals", logic: "OR" } // Production //{ fieldName: "RowType", expr: 20, cond: "doesNotEqual" }, // Order Info //{ fieldName: "RowType", expr: 50, cond: "doesNotEqual" }, // Picked / Ready //{ fieldName: "RowType", expr: 60, cond: "doesNotEqual" }, // Picked / Ready Summary //{ fieldName: "RowType", expr: 70, cond: "doesNotEqual" }, // Purchase Order //{ fieldName: "RowType", expr: 80, cond: "doesNotEqual" } // Inbound Transfer ]; break; } return filters; }
Here's how I've defined the columns, in case I've messed something up there:
// Define the schema var schemaFields = [ { name: "RowType", type: "number" }, { name: "RowFormat", type: "number" }, { name: "Oversold", type: "string" }, { name: "Status", type: "string" }, { name: "OrderNumberInfo", type: "string" }, { name: "GeneralDescription", type: "string" }, { name: "RowDate", type: "string" }, { name: "RowDateFormat", type: "number" }, { name: "MultiIndicator", type: "string" }, { name: "FobOrTransfer", type: "string" }, { name: "PackageSize", type: "string" }, { name: "BoardFeet", type: "number" } ]; // Define the gridColumns var columnsArray = [ { headerText: "", key: "RowType", dataType: "number", hidden: true }, { headerText: "", key: "RowFormat", dataType: "number", hidden: true }, { headerText: "", key: "Oversold", width: "25px", dataType: "string" }, { headerText: "", key: "Status", width: "25px", dataType: "string" }, { headerText: "", key: "OrderNumberInfo", width: "100px", dataType: "string" }, { headerText: "", key: "GeneralDescription", width: "200px", dataType: "string" }, { headerText: "", key: "RowDate", width: "150px", dataType: "string" }, { headerText: "", key: "RowDateFormat", dataType: "number", hidden: true }, { headerText: "", key: "MultiIndicator", width: "20px", dataType: "string" }, { headerText: "", key: "FobOrTransfer", width: "100px", dataType: "string" }, { headerText: "Pkg", key: "PackageSize", width: "75px", dataType: "string" }, { headerText: "Brd Ft", key: "BoardFeet", width: "90px", dataType: "number", format: "###,###,###" } ]; // Define the column Settings var filterColumnSettings = [ { columnKey: "RowType", allowFiltering: true }, { columnKey: "RowFormat", allowFiltering: false }, { columnKey: "Oversold", allowFiltering: false }, { columnKey: "Status", allowFiltering: false }, { columnKey: "OrderNumberInfo", allowFiltering: false }, { columnKey: "GeneralDescription", allowFiltering: false }, { columnKey: "RowDate", allowFiltering: false }, { columnKey: "RowDateFormat", allowFiltering: false }, { columnKey: "MultiIndicator", allowFiltering: false }, { columnKey: "FobOrTransfer", allowFiltering: false }, { columnKey: "PackageSize", allowFiltering: false }, { columnKey: "BoardFeet", allowFiltering: false } ];
The filtering is NOT currently working