Hi I'm facing a weird problem that only happens in FF. I have a TextBox control with OnTextChanged handler. The event handler is working fine most of the time, but when the user changed the text and press Enter in FF, the OnTextChanged event is called twice. I observed the problem in Firebug that the first request is actually canceled because of the second event.
Test.aspx
<%# Page Language="C#" AutoEventWireup="True" CodeFile="~/Test.aspx.cs" Inherits="T.Test" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Custom TextBox - OnTextChanged - C# Example</title>
</head>
<body>
<form id="Form1" method="post" runat="server">
<asp:ScriptManager runat="server" ID="SM">
</asp:ScriptManager>
<h3>Custom TextBox - OnTextChanged - C# Example</h3>
<asp:UpdatePanel runat="server" ID="Panel1">
<ContentTemplate>
<asp:Panel runat="server" ID="Panel2">
<asp:TextBox ID="TextBox1" AutoPostBack="true" OnTextChanged="OnTextChanged" runat="server">Hello World!
</asp:TextBox>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
Test.aspx.cs
using System;
using System.Web.UI;
namespace T
{
public partial class Test : Page
{
protected void OnTextChanged(object sender, EventArgs e)
{
var a = 0;
}
}
}
Put a break point # var a, and you'll be able to see that after changing text and press enter in FF (v3.5.7), the OnTextChanged event is invoked twice.
So my question is, what's the best way to properly handle OnTextChanged event so that hitting enter in the textbox doesn't trigger double postback.
Regards,
I don't know why it's isolated to FireFox, but if you remove the AutoPostBack property, that will solve the problem.
There is also an explanation here of why it's posting back twice.
I know its an old thread but maybe helpful for others.
I had the same issue when validating the text entered. I was getting 2 events fired so I put this script at the top of the page which causes the enter to just tab to the next control instead of submitting the form. The text box remained the same AutoPostBack="true" OnTextChanged="xxx_TextChanged"
''''
<script type="text/javascript">
$('body').on('keydown', 'input, select', function (e) {
if (e.key === "Enter") {
var self = $(this), form = self.parents('form:eq(0)'), focusable, next;
focusable = form.find('input,a,select,button,textarea').filter(':visible');
next = focusable.eq(focusable.index(this) + 1);
if (next.length) {
next.focus();
} else {
form.submit();
}
return false;
}
});
</script>
''''
Related
I came across a very strange occurrence with ASP.NET onclick event in IE (other browsers doesn't seem to have this problem). When there is only one textbox field in a form, the onclick event doesn't fire when you enter text and hit Enter/Return. The event does fire when you click on the actual submit button. When there are two or more fields in the form, hitting Enter/Return works just fine.
It's very strange. Thought it was something with my IE, but checked other machines, and every one of them had the same problem.
I had setup this really simple page as a test:
<%# Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void btnSubmit_Click(object sender, EventArgs e)
{
Response.Write(((Button)sender).Text);
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="txtBox1" runat="server"></asp:TextBox>
<asp:TextBox ID="txtBox2" runat="server" ></asp:TextBox>
<asp:Button ID="btnSubmit" OnClick="btnSubmit_Click" Text="Submit" runat="server" />
</div>
</form>
</body>
</html>
When one of the textbox is removed, the btnSubmit_Click event doesn't behave as expected.
The defaultButton property of Panel or Form is used to ensure Enter Key Submission. Typically people used to Enter Key submission and if it is disabled, it might be annoying certain times.
The defaultButton really provides a way to handle Enter Keys for respective portions of the page when the focus is there.
Source: multiple submit buttons and the enter key
I've tried to wrap up my problem with a complete example below - the original problem is part of a jQuery plug-in that I'm writing to extend the behaviour of an ASP.NET ajax application I already have.
The aspx page below has one drop down list which is marked for auto post back. I've also bound a change event using jquery (which ultimately I will swap for a .live() event to maintain the binding after the update panel refresh.) The problem is, when the jQuery event is bound I see two ajax begin requests and page_loads fire but only one ddlTest_OnselectedIndexChanged event. One of the page loads is malformed too - the content-length states it's about 300 bytes long whilst the totalBytes is 0 and form data empty. This does not happen if I bind to the click event of a button.
Can someone explain why the erroneous page_load event is firing please??
<%# Page Language="C#" AutoEventWireup="true" %>
<%# Import Namespace="System.Diagnostics" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<script runat="server">
private void Page_Load(object sender, EventArgs e)
{
Debug.WriteLine(Request.Headers["Content-Length"]);
Debug.WriteLine(Request.TotalBytes);
Debug.WriteLine(Request.Form.ToString());
Debugger.Break();
}
private void ddlTest_OnSelectedIndexChanged(object sender, EventArgs e)
{
Debugger.Break();
}
</script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<script type="text/javascript" language="javascript">
$(document).ready(function() {
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginRequestHandler);
$("#<%=ddlTest.ClientID%>").change(function() { alert('jQuery binding fired'); });
});
function beginRequestHandler() {
alert("Started ajax call");
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="SciptManager" runat="server" />
<asp:UpdatePanel ID="updTest" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:DropDownList ID="ddlTest" runat="server" AutoPostBack="true" OnSelectedIndexChanged="ddlTest_OnSelectedIndexChanged" >
<asp:ListItem>First</asp:ListItem>
<asp:ListItem>Second</asp:ListItem>
</asp:DropDownList>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
Update : I've narrowed the problem down even further. Firefox and Chrome both work as I would expect whilst IE is having a problem. I've also simplified the erroneous code to the example below. It's hard to believe it's this simple but the jQuery .change() method on the drop down list triggers the onchange event on the select element twice! I'll look for other people who've had this problem and report back my findings!
<%# Page Language="C#" AutoEventWireup="true"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<script type="text/javascript" language="javascript">
$(document).ready(function() {
$('#ddlTest').change(function() { alert('jQuery event fired'); });
});
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:DropDownList id="ddlTest" runat="server" onchange="alert('element event');">
<asp:ListItem Text="First" />
<asp:ListItem Text="Second" />
</asp:DropDownList>
</form>
</body>
</html>
The call of $("#<%=ddlTest.ClientID%>").change(... is probably trigger your drop down list and because of your autopostBack, you get an second refresh of your page.
It looks like I've uncovered a bug in the latest version of jQuery :(. If I change the test back to version 1.3.2 it works fine! I've also found a reference to a bug raised with jQuery.
Take out the autopostback=true = it is firing one postback and the change event is another.
<asp:RadioButtonList ID="RdoBtnHasNotified" runat="server" RepeatDirection="Horizontal" AutoPostBack="True" OnSelectedIndexChanged="RdoBtnHasNotified_SelectedIndexChanged">
<asp:ListItem Value="1">Yes</asp:ListItem>
<asp:ListItem Value="0" Selected="True">No</asp:ListItem>
</asp:RadioButtonList>
<asp:TextBox ID="TxtHowNotified" runat="server" TextMode="MultiLine" MaxLength="100"></asp:TextBox>
I want to enable the TextBox by clicking on the RadioButtonList, without using autopostback=true. How can I do this with JavaScript?
You can use jQuery to manipulate input's enabled state (HTML translation for TextBox) or you can use ASP.NET Ajax so you can set both controls inside of update panel in this case you won't see page being reloaded on postback which must happen in order for you to change status of TextBox on some other event.
Tbh i would go with ASP.NET Ajax because my experience shows that jQuery does not work that well with ASP.NET controls when it comes to complex stuff ie. ASP.NET uses javascript for event activation which can cause either jQuery or ASP.NET not to work as you may expected.
Good luck with update panels...
Using jQuery, you can have a fairly custom result by hooking in to the changes on the radio buttons...
$("#<%= RdoBtnHasNotified.ClientID %> > input[type=radio]").change(function(){
// this function is called whenever one of the radio button list's control's change
// the $(this) variable refers to the input control that triggered the event
var txt = $("#<%= TxtHowNotified.ClientID %>");
if($(this).val()=="1") {
txt.removeAttr("disabled");
} else {
txt.attr("disabled", true);
}
});
Each ListItem renders a radio button with the same name parameter; I would suggest running the app and looking at the generated source to get an idea of what you need to do to listen for the radio button events. Essentially the ID of the radio button list is the name parameter, so you can get the group of radio buttons as (using JQuery):
$("input[name='<%= rbl.ClientID%>']").click(function() {
var tb = $("#textboxid");
//do something here; this points to the radio button
});
HTH.
Here you go:
<%# Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void RdoBtnHasNotified_PreRender(object sender, EventArgs e)
{
foreach (ListItem item in RdoBtnHasNotified.Items)
item.Attributes.Add("onclick", string.Format("toggleTextBox(this,'{0}');", TxtHowNotified.ClientID));
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript">
function toggleTextBox(radioButton, textBoxId) {
document.getElementById(textBoxId).disabled = radioButton.value != "1";
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:RadioButtonList ID="RdoBtnHasNotified" OnPreRender="RdoBtnHasNotified_PreRender"
runat="server" RepeatDirection="Horizontal">
<asp:ListItem Value="1">Yes</asp:ListItem>
<asp:ListItem Value="0" Selected="True">No</asp:ListItem>
</asp:RadioButtonList>
<asp:TextBox ID="TxtHowNotified" runat="server" TextMode="MultiLine" MaxLength="100" Enabled="false"></asp:TextBox>
</div>
</form>
</body>
</html>
Write the code in the following way
<script type="text/javascript">
$(document).ready(function() {
$("input[name='RdoBtnHasNotified']").change(function() {
$("input[name='RdoBtnHasNotified']:checked").val() == '1' ? $('#TxtHowNotified').removeAttr("disabled") : $('#TxtHowNotified').attr('disabled', 'true');
});
});
</script>
and also disable the textbox (Enabled="false") since initialy the value of the "RdoBtnHasNotified" is "No".
$('#<%= RdoBtnHasNotified.ClientID %> > input[type=radio]').click(function()
{
var txtbox = $('#<%= TxtHowNotified.ClientID %>');
if($(this).val() == '1')
{
document.getElementById('#<%= TxtHowNotified.ClientID %>').disabled = false;
}
else
{
document.getElementById('#<%= TxtHowNotified.ClientID %>').disabled = true;
}
});
I think using change event will not fire in IE.
I'm trying to stop postback on form submit if my custom jQuery validation returns false.
Is there any way to prevent the __doPostback() function finishing from within the submit() function?
I'd assumed:
$('#aspnetForm').submit(function () { return false; });
would do the trick, but apparently that's not the case: does anyone have a suggestion?
The submit() function does block the postback (it won't postback if you pause at a breakpoint in firebug), but I can't seem to stop the event happening after the submit() function is complete!
Cheers, Ed
EDIT
OK, I had a quick mess about and discovered that the fact that the button I'm using to cause the postback is tied to an updatepanel as an asyncpostbacktrigger seems to be the problem: If I remove it as a trigger (i.e. cause it to product a full postback), the is no problem preventing the postback with return false;
Any ideas why the async postback would not be stoppable using return false?
You have to use the client side PageRequestManager to properly handle AJAX submit events. (e.g. prevent an async postback.)
If you are not in total control of the page, there can be JavaScript on the page that just calls __doPostBack() without going through any page logic.
In this case - in addition to the above -, you have to store the old window.__doPostBack() and provide your own - as #tucaz mentioned in his comments.
(...and as you mentioned, it can get quite perplexing with chaining.)
For regular submits (non-AJAX), you can provide an event handler as others have pointed out.
This page might be of help and has some code samples that use PageRequestManager. In particular:
initialize : function()
{
...
this._onSubmitHandler = Function.createDelegate(this, this._onSubmit);
this._onPartialUpdateEnd = Function.createDelegate(this, this._onUpdateEnd);
if (typeof(Sys.WebForms)!== "undefined" && typeof(Sys.WebForms.PageRequestManager)!== "undefined")
{
Array.add(Sys.WebForms.PageRequestManager.getInstance()._onSubmitStatements, this._onSubmitHandler);
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(this._onPartialUpdateEnd);
}
else
$addHandler(document.forms[0], "submit", this._onSubmitHandler);
},
Edit:
Following the above, this, for example works fine for me (.Net 3.5 SP1, Button1 is trigger in the updatepanel, etc...):
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="http://ajax.microsoft.com/ajax/jQuery/jquery-1.4.2.js" charset="utf-8"
type="text/javascript"></script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<div>
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</div>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button1" />
</Triggers>
</asp:UpdatePanel>
</form>
<script type="text/javascript">
(function($, undefined) {
var submitHandler = function(e) {
return false;
}
if (typeof (Sys.WebForms) !== "undefined" && typeof (Sys.WebForms.PageRequestManager) !== "undefined") {
Array.add(Sys.WebForms.PageRequestManager.getInstance()._onSubmitStatements, submitHandler);
} else {
$("form").submit(submitHandler);
}
})(jQuery);
</script>
</body>
</html>
$('#yourPostButton').click(function(){
return false;
});
This should do!
We have a checkbox that is initially disabled and checked. It is then enabled on the client side through javascript. If the user then unchecks the box and presses the button to invoke a postback, the state of the checkbox remains as checked on the server side. This is obviously undesirable behaviour. Here is an example.
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="testcb.aspx.cs" Inherits="ESC.testcb" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<script type="text/javascript">
function buttonClick() {
var cb = document.getElementById('<%= CheckBox1.ClientID %>');
cb.disabled = false;
cb.parentNode.disabled = false;
}
</script>
<div>
<asp:CheckBox ID="CheckBox1" runat="server" Checked="true" Enabled="false" />
<asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="buttonClick(); return false;" />
<asp:Button ID="Button2" runat="server" Text="Button2" OnClick="button2Click" />
</div>
</form>
</body>
</html>
And the Server-side code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ESC
{
public partial class testcb : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void button2Click(object sender, EventArgs e)
{
string h = "";
}
}
}
So we break at the "string h" line and check the value of CheckBox1.Checked. It is true, even if it is unchecked on the form.
This is a known problem with ASP.NET - for some reason ASP.NET won't update a checkbox on postback if it was disabled during page load and not checked for postback. I don't know exactly why that is though - if you make the checkbox unselected by default and select it, the value is changed on the server correctly.
The workaround is to add a hidden field to the page that represents the state of the checkbox, then update the field's value to "ON" or "OFF" for example, whenever the checkbox is clicked.
Then on the server you check the value of the hidden field, not the checkbox itself, as the hidden field is always posted.
I had a similar problem to this where the Checked property of the CheckBox object was not being updated correctly, to get the actual posted value you can check:
Request.Form[CheckBox1.UniqueID]
it will be 'on' if the box is checked and null if not.
Since you're already using Javascript to manipulate the controls state in the browser, I suggest you just disable the checkbox on the page load event in stead. Then your postbacks will work just fine...
<head>
<script type="text/javascript">
function buttonClick() {
var cb = document.getElementById('<%= CheckBox1.ClientID %>');
cb.disabled = false;
cb.parentNode.disabled = false;
}
</script>
</head>
<body onload="document.getElementById('<%= CheckBox1.ClientID %>').disabled = true;">
<form id="form1" runat="server">
<div>
<asp:checkbox id="CheckBox1" runat="server" checked="true" />
<asp:button id="Button1" runat="server" text="Button" onclientclick="buttonClick(); return false;" />
<asp:button id="Button2" runat="server" text="Button2" onclick="button2Click" />
</div>
</form>
</body>
I may not understand the problem correctly, but can't you just use the Form from the Request to retrieve the CheckBox value? So in button2Click() in the code behind file you'd do this:
Request.Form[CheckBox1.UniqueID]
You can use something like this.
if ((Request.Params["Checkbox1"] ?? "").ToString() == "on")
If it isn't checked it won't pass it in the first place, but this should account for that.
Here is an alternative solution if you need to avoid recompiling your source code.
It just enables the checkbox for a split second before submitting the form.
1: Add the following parameter to your submit button:OnClientClick="EnableCheckbox()"
2: Add this simple function somewhere on the page to enable it
<script>
function EnableCheckbox() {
document.getElementById("<%=chkMyCheckbox.clientID %>").disabled = false;
}
</script>