We have a web app that has run perfectly since 2018 until we made a minor change.
This is app allows user to dynamically add a new row as needed.
Recently, we were instructed to create a DropdownList that dynamically displays or hides some controls based on selection from the DropdownList.
The issue we are currently having is that each time you click a button to add a new row, though the new row gets created but the mouse quickly jumps and focuses on the dropdown.
User will have to scroll back down to the row just added.
Below is the code we are currently using.
//HTML
<asp:DropDownList ID="ddlChoice" AutoPostBack="true" style="background-color:#0093B2;border: 2px solid #92b200;width:310px;color:white;border-width:5px;" runat="server" class="form-control select2-selection select2-selection--single form-control input-lg" role="combobox" aria-haspopup="true" aria-expanded="false" aria-labelledby="select2-e8ez-container" OnSelectedIndexChanged="ddlChoice_Changed">
<asp:ListItem Text="Please select >>" Value="" />
<asp:ListItem Text="I want to use my ID Card" Value="CardNo" />
<asp:ListItem Text="I want to use my SS number" Value="SSNo" />
</asp:DropDownList><br />
<asp:RequiredFieldValidator ID="rfvDDL" runat="server"
ControlToValidate="ddlChoice"
Display="Dynamic"
ErrorMessage="Please make your selection."
InitialValue=""
ForeColor="Red" >
</asp:RequiredFieldValidator>
<div class="table-responsive">
<asp:gridview ID="Gridview1" RowStyle-Wrap="false" gridlines="None" runat="server" ShowFooter="true" AutoGenerateColumns="false" onrowdatabound="Gridview1_RowDataBound" OnRowDeleting="Gridview1_RowDeleting">
<Columns>
<asp:BoundField DataField="RowNumber" Visible="false" HeaderText="Row Number" />
<asp:TemplateField HeaderText="Name">
<headerstyle horizontalalign="Left" />
<ItemTemplate>
<asp:TextBox ID="txtname" TabIndex="4" Text='<%# Eval("ename") %>' placeholder="Name...(e.g, ABC, Inc.)" runat="server" style="width:375px;" AutoPostBack="true" class="form-control textClass align-left" OnTextChanged="txtname_TextChanged"></asp:TextBox><br />
<asp:CheckBox ID="grid1Details" ClientIDMode="Static" runat="server" Checked="false" AutoPostBack="true" OnCheckedChanged="Grid1CheckChanged" /><span id="srcemp" runat="server" style="color:#ff0000">*Check this box if N/A</span>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Address">
<ItemStyle HorizontalAlign="Left"></ItemStyle>
<ItemTemplate>
<asp:TextBox ID="txtaddress" TabIndex="5" Text='<%# Eval("address") %>' placeholder="Address..." runat="server" style="width:375px;" class="form-control textClass align-left" AutoPostBack="true" OnTextChanged="txtname_TextChanged"></asp:TextBox><br /><br />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:Button ID="ButtonAdd" runat="server" OnClientClick="BtnClick();" CausesValidation="true" Text="Add another row if needed"
onclick="ButtonAdd_Click" style="border: 1px solid #6E6E6E;font-family: 'Arial Unicode MS';background-color: #0093B2;color: #FFFFFF;font-size: 12pt;font-style: normal;text-align: center;padding-right: 10px;padding-left: 10px;" /><br /><br /><br>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:Button ID="sourceDelete" runat="server" Text="Delete" CommandName="Delete"
style="border: 1px solid #6E6E6E;font-family: 'Arial Unicode MS';background-color: #0093B2;color: #FFFFFF;font-size: 12pt;font-style: normal;text-align: center;padding-right: 10px;padding-left: 10px;" OnClientClick="return confirm('Are you sure you want to remove this row?')" /> <br /><br /><br />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:gridview>
</div>
//VB
Protected Sub ddlChoice_Changed(ByVal sender As Object, ByVal e As EventArgs)
If ddlChoice.SelectedItem.Value = "CardNo" Then
pnlCardNo.Visible = True
pnlSSNO.Visible = False
Else
pnlCardNo.Visible = False
pnlSSNO.Visible = True
End If
End Sub
//jS
<script type="text/javascript">
function BtnClick() {
var val = Page_ClientValidate();
if (!val) {
var i = 0;
for (; i < Page_Validators.length; i++) {
if (!Page_Validators[i].isvalid) {
$("#" + Page_Validators[i].controltovalidate)
.css("border-color", "red");
}
}
}
return val;
}
</script>
<asp:Button ID="ButtonAdd" runat="server" OnClientClick="BtnClick();" CausesValidation="true" Text="Add another row if needed"
Protected Sub ButtonAdd_Click(sender As Object, e As EventArgs) AddNewRowToGrid() End Sub
Private Sub AddNewRowToGrid() Dim rowIndex As Integer = 0
If ViewState("CurrentTable") IsNot Nothing Then
Dim dtCurrentTable As DataTable = DirectCast(ViewState("CurrentTable"), DataTable)
Dim drCurrentRow As DataRow = Nothing
If dtCurrentTable.Rows.Count > 0 Then
Dim txtsoname As TextBox = Nothing
Dim txtsoaddress As TextBox = Nothing
For i As Integer = 1 To dtCurrentTable.Rows.Count
'extract the TextBox values
txtsoname = DirectCast(Gridview1.Rows(rowIndex).Cells(1).FindControl("txtsourcename"), TextBox)
txtsoaddress = DirectCast(Gridview1.Rows(rowIndex).Cells(2).FindControl("txtsourceaddress"), TextBox)
drCurrentRow = dtCurrentTable.NewRow()
drCurrentRow("RowNumber") = i + 1
dtCurrentTable.Rows(i - 1)("sourcename") = txtsoname.Text
dtCurrentTable.Rows(i - 1)("sourceaddress") = txtsoaddress.Text
rowIndex += 1
Next
If Not String.IsNullOrEmpty(txtsoname.Text) AndAlso Not String.IsNullOrEmpty(txtsoaddress.Text) Then
dtCurrentTable.Rows.Add(drCurrentRow)
Else
ScriptManager.RegisterStartupScript(Me, Me.GetType(), "Confirm", "jAlert('Please complete first row before adding a new row!');", True)
End If
'dtCurrentTable.Rows.Add(drCurrentRow)
ViewState("CurrentTable") = dtCurrentTable
Gridview1.DataSource = dtCurrentTable
Gridview1.DataBind()
End If
Else
Response.Write("ViewState is null")
End If
SetPreviousData()
End Sub
Any ideas how to fix this issue?
Ok, as per my comments, there is nothing that looks to have changed from what you had previous, to what you had/have now.
With the posted code, and a post-back, I see no code that in the past that attempts to set the focus, and thus clicking on a check box (with a post-back), or clicking on that Add New row button, once again, it re-binds the GridView.
I suggest adding some code to set focus to the last new row when the user hits add new row.
Hence, one could simply add some code to set focus to the first text box on that new row you just added.
So, your code after the GridView binding could be this:
GridView1.DataBind()
Dim LastRow As GridViewRow = GridView1.Rows(GridView1.Rows.Count - 1)
Dim txtName As TextBox = LastRow.FindControl("txtname")
txtName.Focus()
So, the above should thus set the focus to the text box of the newly added row. And if that row is below the current view of the browser, then using .Focus() method of that control should scroll the browser down to that new row, and set the cursor and focus to that text box.