Get GridView selected row DataKey in Javascript - asp.net

I have GridView which I can select a row. I then have a button above the grid called Edit which the user can click to popup a window and edit the selected row. So the button will have Javascript code behind it along the lines of
function editRecord()
{
var gridView = document.getElementById("<%= GridView.ClientID %>");
var id = // somehow get the id here ???
window.open("edit.aspx?id=" + id);
}
The question is how do I retrieve the selected records ID in javascript?

I worked it out based on JasonS response. What I did was create a hidden field in the Grid View like this:
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<asp:HiddenField ID="hdID" runat="server" Value='<%# Eval("JobID") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField Visible="False">
<ItemTemplate>
<asp:LinkButton ID="lnkSelect" runat="server" CommandName="select" Text="Select" />
</ItemTemplate>
</asp:TemplateField>
Then on the OnRowDataBind have code to set the selected row
protected virtual void Grid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Click to highlight row
Control lnkSelect = e.Row.FindControl("lnkSelect");
if (lnkSelect != null)
{
StringBuilder click = new StringBuilder();
click.AppendLine(m_View.Page.ClientScript.GetPostBackClientHyperlink(lnkSelect, String.Empty));
click.AppendLine(String.Format("onGridViewRowSelected('{0}')", e.Row.RowIndex));
e.Row.Attributes.Add("onclick", click.ToString());
}
}
}
And then in the Javascript I have code like this
<script type="text/javascript">
var selectedRowIndex = null;
function onGridViewRowSelected(rowIndex)
{
selectedRowIndex = rowIndex;
}
function editItem()
{
if (selectedRowIndex == null) return;
var gridView = document.getElementById('<%= GridView1.ClientID %>');
var cell = gridView.rows[parseInt(selectedRowIndex)+1].cells[0];
var hidID = cell.childNodes[0];
window.open('JobTypeEdit.aspx?id=' + hidID.value);
}
</script>
Works a treat :-)

1) change your javascript function to use a parameter
function editRecord(clientId)
{ ....
2) output the call in your editRecord button... if you want to avoid dealing with the .net generated ids, just use a simple
<input type="button" onclick="editRecord(your-rows-client-id-goes-here)" />

Based off of your comments to #DaveK's response, in javascript you can set the id of a hidden field to the clientId of the selected row when the user selects it. Then have your editRecord function use the value set on the hidden form field.

one could avoid javascript altogether, by setting anchor tags pre-populated with the query string for each row (although this will effect your table layout, it will need only one click rather than 2 from the user)
insert in the gridview template:
<asp:HyperLink runat="server" ID="editLink" Target="_blank"
NavigateURL='<%# Eval("JobID","edit.aspx?id={0}") %>'>
Edit..
</asp:HyperLink>

Related

select data from gridview field and populate textbox

I'm trying to populate a single text box (or parameter) with data from a gridview column when I click on a button in that row.
Gridview gets it data from a sqlconnection
the gridview is
| Drawing |
| 12345 | VIEW
| 12346 | VIEW
the VIEW is a template button with an onclick event, when the user clicks the button the data from the Drawing column (12345) should be passed to ether a textbox or a paremeter. (this is the part I dont know how to do) once the Iv got the number in a textbox I can use it as pareameter and then a pdf is opened of that drawing, I have code for this and is working.
thanks for any help
If you are using C#, the simplest thing to do would be to add an in-built select command button to the gridview rows at runtime. Then on the selectedindexchanged event of the gridview simply access the cell of the selected row that you want the value from. You can then assign that string to anything you want. Like so:
protected void myGridView_SelectedIndexChanged(object sender, EventArgs e)
{
string myString = myGridView.SelectedRow.Cells[4].Text.ToString();
TextBox1.Text = myString;
}
Remember that the cell index collection is zero based, so [0] is actually the first cell in the row.
Use TemplateFields and the grid view's OnRowCommand event, like this:
Markup:
<asp:gridview id="GridView1"
OnRowCommand="GridView1_RowCommand"
runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox ID="TextBoxDrawing" runat="server"
Text="<%# Eval("Drawing")) %>" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="selc" runat="server" Text="View"
CommandName="View"
CommandArgument="<%# ((GridViewRow)Container).RowIndex %> />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code-behind:
protected void GridView1_RowCommand(Object sender, GridViewCommandEventArgs e)
{
// If multiple buttons are used in a GridView control, use the
// CommandName property to determine which button was clicked
if(e.CommandName == "View")
{
// Convert the row index stored in the CommandArgument
// property to an integer
var index = Convert.ToInt32(e.CommandArgument);
// Retrieve the row that contains the button clicked
// by the user from the Rows collection
var row = GridView1.Rows[index];
// Find the drawing value
var theDrawingTextBox = row.FindControl("TextBoxDrawing") as TextBox;
// Verify the text box exists before we try to use it
if(theDrawingTextBox != null)
{
var theDrawingValue = theDrawingTextBox.Text;
// Do something here with drawing value
}
}
}

Default selection of header and item checkboxes in gridview in asp.net

I have gridview with header and item checkboxes.when i select header checkbox my code able to select all item checkboxes.when i un select header checkbox my code able to un select all item checkboxes.
Here my issue is when my page is loading(means when grid is loading first time) by default the header and item checkboxes should be selected.how can we do this.
Use RowDataBound Event in Gridview
protected void GridViewName_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row .RowType == DataControlRowType .DataRow )
{
//Your Code
}
}
In grid view columns write like this
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<asp:CheckBox ID="chkhead" runat="server" onclick="SelectAllCheckboxes(this)" ClientIDMode="Static" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="chksub" runat="server" ClientIDMode="Static" />
</ItemTemplate>
</asp:TemplateField>
After that write the Java script function SelectAllCheckboxes
// select all check boxes
function SelectAllCheckboxes(spanChk) {
// Added as ASPX uses SPAN for checkbox
var oItem = spanChk.children;
var theBox = (spanChk.type == "checkbox") ?
spanChk : spanChk.children.item[0];
xState = theBox.checked;
elm = theBox.form.elements;
for (i = 0; i < elm.length; i++)
if (elm[i].type == "checkbox" && elm[i].id != theBox.id) {
//elm[i].click();
if (!elm[i].disabled) {
if (elm[i].checked != xState)
elm[i].click();
}
//elm[i].checked=xState;
}
}
After write the .cs page load event first bind the grid view and chheader.checked=true;

How to add a "confirm delete" option in ASP.Net Gridview?

How to add a "confirm delete" option in ASP.Net Gridview ?
This should do it.
I found it here: http://forums.asp.net/p/1331581/2678206.aspx
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<asp:ImageButton ID="DeleteButton" runat="server" ImageUrl="~/site/img/icons/cross.png"
CommandName="Delete" OnClientClick="return confirm('Are you sure you want to delete this event?');"
AlternateText="Delete" />
</ItemTemplate>
</asp:TemplateField>
If your Gridview used with AutoGenerateDeleteButton="true" , you may convert it to LinkButton:
Click GridView Tasks and then Edit Columns.
Select Delete in Selected fields, and click on Convert this field into a TemplateField. Then click OK:
Now your LinkButton will be generated. You can add OnClientClick event to the LinkButton like this:
OnClientClick="return confirm('Are you sure you want to delete?'); "
I did this a bit different. In my gridview I set the AutoGenerateDeleteButton="true". To find the delete button I use jQuery and add a click event to the found Anchors.
jQuery("a").filter(function () {
return this.innerHTML.indexOf("Delete") == 0;
}).click(function () { return confirm("Are you sure you want to delete this record?");
});
This is quick and simple for what I need to do. Just be mindful that Every Anchor in the page that displays Delete will be selected by jQuery and will have the event added to it.
I like this way of adding a confirmation prompt before deleting a record from a gridview. This is the CommandField definition nested within a GridView web control in the aspx page. There's nothing fancy here--just a straightforward Commandfield.
<asp:CommandField ShowEditButton="true" UpdateText="Save" ShowDeleteButton="True">
<ControlStyle CssClass="modMarketAdjust" />
</asp:CommandField>
Then, all I had to do was add some code to the RowDeleting event of the GridView control. This event fires before the row is actually deleted, which allows you to get the user's confirmation, and to cancel the event if he doesn't want to cancel after all. Here is the code that I put in the RowDeleting event handler:
Private Sub grdMarketAdjustment_RowDeleting(sender As Object, e As GridViewDeleteEventArgs) Handles grdMarketAdjustment.RowDeleting
Dim confirmed As Integer = MsgBox("Are you sure that you want to delete this market adjustment?", MsgBoxStyle.YesNo + MsgBoxStyle.MsgBoxSetForeground, "Confirm Delete")
If Not confirmed = MsgBoxResult.Yes Then
e.Cancel = True 'Cancel the delete.
End If
End Sub
And that seems to work fine.
I didn't want any image so i modified the answer given by #statmaster to make it simple entry along with the other columns.
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CommandName="Delete" OnClientClick="return confirm('Are you sure you want to delete this entry?');">Delete </asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
The colour of the text can be changed using the Forecolor Property.
You can do using OnClientClick of button.
OnClientClick="return confirm('confirm delete')"
I quite like adding the code in the GridView RowDataBound event to inform the user exactly which item they are trying to delete. Slightly better user experience?
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
LinkButton lnkBtnDelete = e.Row.FindControl("lnkBtnDelete") as LinkButton;
// Use whatever control you want to show in the confirmation message
Label lblContactName = e.Row.FindControl("lblContactName") as Label;
lnkBtnDelete.Attributes.Add("onclick", string.Format("return confirm('Are you sure you want to delete the contact {0}?');", lblContactName.Text));
}
}
Try this:
I used for Update and Delete buttons. It doesn't touch Edit button. You can use auto generated buttons.
protected void gvOperators_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType != DataControlRowType.DataRow) return;
var updateButton = (LinkButton)e.Row.Cells[0].Controls[0];
if (updateButton.Text == "Update")
{
updateButton.OnClientClick = "return confirm('Do you really want to update?');";
}
var deleteButton = (LinkButton)e.Row.Cells[0].Controls[2];
if (deleteButton.Text == "Delete")
{
deleteButton.OnClientClick = "return confirm('Do you really want to delete?');";
}
}
This is my preferred method. Pretty straight forward:
http://www.codeproject.com/KB/webforms/GridViewConfirmDelete.aspx
Although many of these answers will work, this shows a straightforward example when using CommandField in GridView using the OnClientClick property.
ASPX:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" OnRowDataBound="OnRowDataBound"... >
<Columns>
<!-- Data columns here -->
<asp:CommandField ButtonType="Button" ShowEditButton="true" ShowDeleteButton="true" ItemStyle-Width="150" />
</Columns>
</asp:GridView>
ASPX.CS:
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow && e.Row.RowIndex != GridView1.EditIndex)
{
(e.Row.Cells[2].Controls[2] as Button).OnClientClick = "return confirm('Do you want to delete this row?');";
}
}
I was having problems getting a commandField Delete button to honor the 'return false' response to when a user clicked cancel on the 'Are you sure' pop-up that one gets with using the javascript confirm() function. I didn't want to change it to a template field.
The problem, as I see it, was that these commandField Buttons already have some Javascript associated with them to perform the postback. No amount of simply appending the confirm() function was effective.
Here's how I solved it:
Using JQuery, I first found each delete button on the page (there are several), then manipulated the button's associated Javascript based on whether the visitor agreed or canceled the confirming pop-up.
<script language="javascript" type="text/javascript">
$(document).ready(function() {
$('input[type="button"]').each(function() {
if ($(this).val() == "Delete") {
var curEvent = $(this).attr('onclick');
var newContent = "if(affirmDelete() == true){" + curEvent + "};"
$(this).attr('onclick',newContent);
}
});
}
function affirmDelete() {
return confirm('Are you sure?');
}
</script>
This code is working fine for me.
jQuery("a").filter(function () {
return this.innerHTML.indexOf("Delete") == 0;
}).click(function () { return confirm("Are you sure you want to delete this record?");
});
I love the JavaScript solution and have some updates to work with dynamic ajax loading:
$(document).on("click", "a", function () {
if (this.innerHTML.indexOf("Delete") == 0) {
return confirm("Are you sure you want to delete this record?");
}
});
Hope it help ;)
This is my method and it works perfectly.
asp
<asp:CommandField ButtonType="Link" ShowEditButton="true" ShowDeleteButton="true" ItemStyle-Width="5%" HeaderStyle-Width="5%" HeaderStyle-CssClass="color" HeaderText="Edit"
EditText="<span style='font-size: 20px; color: #27ae60;'><span class='glyphicons glyph-edit'></span></span>"
DeleteText="<span style='font-size: 20px; color: #c0392b;'><span class='glyphicons glyph-bin'></span></span>"
CancelText="<span style='font-size: 20px; color: #c0392b;'><span class='glyphicons glyph-remove-2'></span></span>"
UpdateText="<span style='font-size: 20px; color: #2980b9;'><span class='glyphicons glyph-floppy-saved'></span></span>" />
C# (replace 5 with the column number of the button)
if ((e.Row.RowState & DataControlRowState.Edit) > 0)
{
}
else {
((LinkButton)e.Row.Cells[5].Controls[2]).OnClientClick = "return confirm('Do you really want to delete?');";
}

How do I find the Client ID of control within an ASP.NET GridView?

I have a asp:GridView which contains a asp:TextBox within a TemplateField. I would like to obtain it's ID for use in javascript. Something like this:
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox ID="textDateSent" runat="server" />
<input type="button" value='Today'
onclick="setToday('<%# textDateSent.ClientID %>');" />
</ItemTemplate>
</asp:TemplateField>
But when I compile, I get an error:
The name 'textDateSent' does not exist in the current context
Anybody know how to get the client ID of this TextBox?
Try this:
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox ID="textDateSent" runat="server">
</asp:TextBox>
<input type="button" value='Today' onclick="setToday('<%# ((GridViewRow)Container).FindControl("textDateSent").ClientID %>');" />
</ItemTemplate>
</asp:TemplateField>
Maybe you don't want to do it where you need the ClientID. Check out this post here where the controls in a row are referenced in a generic way.
Change <%# textDateSent.ClientID %> to <%= textDateSent.ClientID %>.
Argh, you may need to use the OnDataBinding event of the grid view. Then put a literal control in your javascript. Then you can get the clientID of the text box and feed that into your literal control.
protected void GridViewName_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//Create an instance of the datarow
DataRowView rowData = (DataRowView)e.Row.DataItem;
//locate your text box
//locate your literal control
//insert the clientID of the textbox into the literal control
}
}
Look here for a great detailed tutorial on working within this context.
You can get client id like this:
protected void Gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string strClientID = ((TextBox)e.Row.FindControl("txtName")).ClientID;
}
}
This will give unique client ID for each textbox in all rows.
I just do this...
var tbl = document.getElementById('<%=GridView.ClientID%>');
var checkBox = tbl.rows[i].cells[11].getElementsByTagName("input")[0].id;
the cell should always be the same and it gets rendered into an input. You may have to change the number at the end if you have more then one input in that cell. This will give you the new clientid/id of the input object (checkbox or whatever)
This is what I did. In the aspx page I just passed the entire object to the javascript function, so I didn't even meed to client id. In my case the object was a drop down list in the EditItemTemplate of the GridView. I added an html onchange(this) event in the aspx code.
<asp:DropDownList ID="custReqRegionsDDL" runat="server" onchange='custReqRegionsDDLOnChange(this)'>
</asp:DropDownList>
here is my javascript
function custReqRegionsDDLOnChange(myDDL)
{
alert('selected text=' + myDDL.options[myDDL.selectedIndex].text);
}

GridView FindControl returns null when HeaderText is set

I have a GridView...
<asp:GridView EnableViewState="true"
ID="grdResults"
runat="server"
CssClass="resultsGrid"
OnRowDataBound="grdResults_OnRowDataBound"
AutoGenerateColumns="false"
HeaderStyle-CssClass="header"
OnRowCommand="grdResults_OnRowCommand">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblView"
runat="server"
Visible="false"
Text="View">
</asp:Label>
<asp:HyperLink ID="hypEdit"
runat="server"
Visible="false"
Text="(Edit)"
CssClass="edit">
</asp:HyperLink>
<asp:LinkButton ID="btnDelete"
runat="server"
Visible="false"
Text="(Delete)"
CssClass="delete"
CommandName="DeleteItem"
OnClientClick="return confirm('Are you sure you want to delete?')">
</asp:LinkButton>
<asp:HyperLink ID="hypSelect"
runat="server"
Visible="false"
Text="(Select)"
CssClass="select">
</asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
This has one static column containing a label two hyperlinks and a link button and also has a number of dynamically generated columns...
private void SetupColumnStructure(IEnumerable<string> columnNames)
{
var columnNumber = 0;
foreach (var columnName in columnNames)
{
var templateColumn = new TemplateField
{
ItemTemplate = new CellTemplate(columnName)
};
grdResults.Columns.Insert(columnNumber, templateColumn);
columnNumber++;
}
}
As part of the OnRowDataBound handler I retrieve one of the controls in the statically column and set some attributes on it...
protected void grdResults_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
.
.
.
var row = e.Row;
var rowData = row.DataItem as Dictionary<string, object>;
if (rowData != null)
{
if ((bool)rowData[displayEditLink])
{
var hypEdit = (HyperLink)row.FindControl("hypEdit");
hypEdit.NavigateUrl = "~/Pages/Edit.aspx?action=Edit&objectType=" + rowData[objectTypeLiteral] + "&id=" + rowData[objectIdLiteral];
hypEdit.Visible = true;
}
}
.
.
.
}
This all works fine but no column names are displayed. So I then modify the SetupColumnStructure method so that the HeaderText is set on the template field like this...
private void SetupColumnStructure(IEnumerable<string> columnNames)
{
var columnNumber = 0;
foreach (var columnName in columnNames)
{
var templateColumn = new TemplateField
{
ItemTemplate = new CellTemplate(columnName),
HeaderText = columnName
};
grdResults.Columns.Insert(columnNumber, templateColumn);
columnNumber++;
}
}
For some reason this one extra line change causes the row.FindControl("hypEdit"); call in the OnRowDataBound handler to return null.Can anyone see something im missing here or has anyone experienced a similar issue?
UPDATE
I've made sure that I'm not referring to a header or footer row here. Also, if I step over the object reference exception this occurs for every item that is in the DataSource.
Not sure if this helps, but as I expected, when I stepped through the code the table has generated all the columns expected but all cells (DataControlFieldCells) contain no controls when the HeaderText is set, yet all expected controls when it isnt set.
All very strange. Let me know if you can spot anything else.
When you added the HeaderText, a new RowType was added to the gridview. You'll need to check what type of row raised the OnRowDataBound event and take the appropriate action. In your case, just checking if the e.Row.RowType is a DataRow should solve your problem:
protected void grdResults_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
if ((bool)rowData[displayEditLink])
{
var hypEdit = (HyperLink)row.FindControl("hypEdit");
hypEdit.NavigateUrl = "~/Pages/Edit.aspx?action=Edit&objectType=" + rowData[objectTypeLiteral] + "&id=" + rowData[objectIdLiteral];
hypEdit.Visible = true;
}
}
}
Its because the control you are searching for is contained within another control. FindControl() does not look inside control collections of controls. You will need to write a recursiveFindControl() method.
Hope this helps a little!

Resources