So in my RadGrid I have a template column that contains RadDropDownList in the EditItemTemplate. When this is modified in a row I would like to loop through the RadGrid and modify the other RadDropDownList in the other rows. I know how to loop through the grid but having trouble accessing the dropdown since the other rows are not in edit mode. Using the changeCellValue(cellToUpdate, value) of the BatchEditingManager but not having any luck with updating the dropdown.
<BatchEditingSettings EditType="Cell" />
<telerik:GridTemplateColumn HeaderText="IsBudget" UniqueName="IsBudget" SortExpression="IsBudget">
<ItemTemplate>
<asp:Label ID="lblIsBudget" runat="server" Text='<%# Eval("IsBudget") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<telerik:RadDropDownList ID="ddIsBudget" RenderMode="Lightweight" runat="server" DataValueField="IsBudget" >
<Items>
<telerik:DropDownListItem Text="False" Value="False" />
<telerik:DropDownListItem Text="True" Value="True" />
</Items>
</telerik:RadDropDownList>
</EditItemTemplate>
</telerik:GridTemplateColumn>
1 Answer, 1 is accepted
Hi Jerry,
The BatchEditing is delicate functionality that will require special handling. Since it is a Client-Side (JavaScript-based) functionality, everything needs to be done using JavaScript.
Important
Due to the nature of BatchEditing, when using the changeCellValue() method, it will not only change the Cell's value but will also change the DropDownList Value for that cell.
If using the OnClientSelectedIndexChanged event of the DropDownList, or the OnBatchEditCellValueChanged Client-Side event of the Grid, these will be triggered for each cell, then the logic will call the changeCellValue() again, resulting in an Endless Loop.
Solution
To avoid the infinite loop, you will need to create a Global Flag that you can use to distinguish whether the user selected a new item in the DropDownList or was the JavaScript logic.
Here are three (3) important steps to achieve that:
Step 1: Set a Global Flag when the DropDown element of the DropDownList is opened by the User.
// This event only triggers if the user clicks on the DropDownList
// Set a Global Flag that will help us avoid the infinite loop
function OnClientDropDownOpened(sender, args) {
window.__isUserSelecting = true;
}
Step 2: To avoid accidents, clear the Global Flag when the DropDown is Closing and the user did not make any selection
// This event only triggers if the user had opened the DropDownList by Clicking on it
// Do this to remove the Global Flag if the user did not select anything
function OnClientDropDownClosing(sender, args) {
// Condition to check if the Global Flag is defined
if (typeof window.__isUserSelecting != 'undefined') {
// Delete/Remove the Global Flag
window.__isUserSelecting = undefined;
}
}
Step 3: In the SelectedIndexChanged event of the DropDownList
- loop through all rows (except the current one)
- open the desired cell for editing
- find the DropDownList in that cell
- Select an item in the DropDownList
- when all is done, close the Editing
// This event triggers when a Selection changes. Since the BatchEditing will change the selection, this will trigger multiple times
function OnClientSelectedIndexChanged(sender, args) {
// Using the Global Flag as condition to only run the Logic if the Selection was done by the user and not by BatchEditing
if (typeof window.__isUserSelecting != 'undefined' && window.__isUserSelecting == true) {
// Remove/Delete the Global Flag
window.__isUserSelecting = undefined;
// Variables & references
var currentDropDownList = sender; // Current DropDownList
var grid = $find('<%= RadGrid1.ClientID %>'); // Grid
var masterTable = grid.get_masterTableView(); // MasterTable
var batMan = grid.get_batchEditingManager(); // BatchEditing Manager
var dataItems = masterTable.get_dataItems(); // Collection of Telerik.Web.UI.GridDataItem Objects
var currentRowElement = $(currentDropDownList.get_element()).closest('tr')[0]; // Current row (TR) Element
var currentDataItem = currentRowElement && currentRowElement.control ? currentRowElement.control : undefined; // Current Telerik.Web.UI.GridDataItem Object
var newValue = currentDropDownList.get_selectedItem().get_value(); // DropDownList Selected Value
var itemIndexToExclude = (currentDataItem ? currentDataItem.get_itemIndex() : undefined) || -1; // ItemIndex or Row Index of the current Row
// Begin looping through all items
for (var i = 0; i < dataItems.length; i++) {
// Skip running the logic for the Current Row
if (i == itemIndexToExclude) continue;
// Target Row
var rowToBeEdited = dataItems[i];
// Target Cell
var cellElement = rowToBeEdited.get_cell("MyTemplateColumn");
// Open the Cell for Editing
batMan.openCellForEdit(cellElement);
// Find the DropDownList in the Cell
var targetDropDown = $telerik.findControl(cellElement, "RadDropDownList1");
// Find the DropDownList Item by Value
var item = targetDropDown.findItemByValue(newValue);
// Condition to check if Item exists
if (item)
item.select(); // Select the Item
// Close all Edits
batMan._tryCloseEdits(document.body);
}
}
}
Result
Complete Code Example
<telerik:RadGrid ID="RadGrid1" runat="server" AllowPaging="True" Width="300px" OnNeedDataSource="RadGrid1_NeedDataSource">
<MasterTableView AutoGenerateColumns="False" DataKeyNames="ID" EditMode="Batch">
<BatchEditingSettings EditType="Cell" />
<Columns>
<telerik:GridTemplateColumn HeaderText="DropDownList" UniqueName="MyTemplateColumn">
<ItemTemplate>
<%# Eval("MyItem") %>
</ItemTemplate>
<EditItemTemplate>
<telerik:RadDropDownList ID="RadDropDownList1" runat="server" RenderMode="Lightweight" AutoPostBack="false"
OnClientDropDownOpened="OnClientDropDownOpened"
OnClientDropDownClosing="OnClientDropDownClosing"
OnClientSelectedIndexChanged="OnClientSelectedIndexChanged">
<Items>
<telerik:DropDownListItem Text="Item 1" Value="Item 1" />
<telerik:DropDownListItem Text="Item 2" Value="Item 2" />
<telerik:DropDownListItem Text="Item 3" Value="Item 3" />
<telerik:DropDownListItem Text="Item 4" Value="Item 4" />
</Items>
</telerik:RadDropDownList>
<script>
// This event only triggers if the user clicks on the DropDownList
// Set a Global Flag that will help us avoid the infinite loop
function OnClientDropDownOpened(sender, args) {
window.__isUserSelecting = true;
}
// This event only triggers if the user had opened the DropDownList by Clicking on it
// Do this to remove the Global Flag if the user did not select anything
function OnClientDropDownClosing(sender, args) {
// Condition to check if the Global Flag is defined
if (typeof window.__isUserSelecting != 'undefined') {
// Delete/Remove the Global Flag
window.__isUserSelecting = undefined;
}
}
// This event triggers when a Selection changes. Since the BatchEditing will change the selection, this will trigger multiple times
function OnClientSelectedIndexChanged(sender, args) {
// Using the Global Flag as condition to only run the Logic if the Selection was done by the user and not by BatchEditing
if (typeof window.__isUserSelecting != 'undefined' && window.__isUserSelecting == true) {
// Remove/Delete the Global Flag
window.__isUserSelecting = undefined;
// Variables & references
var currentDropDownList = sender; // Current DropDownList
var grid = $find('<%= RadGrid1.ClientID %>'); // Grid
var masterTable = grid.get_masterTableView(); // MasterTable
var batMan = grid.get_batchEditingManager(); // BatchEditing Manager
var dataItems = masterTable.get_dataItems(); // Collection of Telerik.Web.UI.GridDataItem Objects
var currentRowElement = $(currentDropDownList.get_element()).closest('tr')[0]; // Current row (TR) Element
var currentDataItem = currentRowElement && currentRowElement.control ? currentRowElement.control : undefined; // Current Telerik.Web.UI.GridDataItem Object
var newValue = currentDropDownList.get_selectedItem().get_value(); // DropDownList Selected Value
var itemIndexToExclude = (currentDataItem ? currentDataItem.get_itemIndex() : undefined) || -1; // ItemIndex or Row Index of the current Row
// Begin looping through all items
for (var i = 0; i < dataItems.length; i++) {
// Skip running the logic for the Current Row
if (i == itemIndexToExclude) continue;
// Target Row
var rowToBeEdited = dataItems[i];
// Target Cell
var cellElement = rowToBeEdited.get_cell("MyTemplateColumn");
// Open the Cell for Editing
batMan.openCellForEdit(cellElement);
// Find the DropDownList in the Cell
var targetDropDown = $telerik.findControl(cellElement, "RadDropDownList1");
// Find the DropDownList Item by Value
var item = targetDropDown.findItemByValue(newValue);
// Condition to check if Item exists
if (item)
item.select(); // Select the Item
// Close all Edits
batMan._tryCloseEdits(document.body);
}
}
}
</script>
</EditItemTemplate>
</telerik:GridTemplateColumn>
</Columns>
</MasterTableView>
</telerik:RadGrid>
<script runat="server">
protected void RadGrid1_NeedDataSource(object sender, Telerik.Web.UI.GridNeedDataSourceEventArgs e)
{
(sender as RadGrid).DataSource = Enumerable.Range(1, 3).Select(x => new
{
ID = x,
MyItem = "Item " + x
}).ToList();
}
</script>
Please note that this scenario is a very custom solution that is not included out of the box and we can not provide support for it. You can use this as a base idea and adjust it to meet your reuquirements.
Regards,
Attila Antal
Progress Telerik
Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.