Here's a simple version of my code:
<asp:TextBox ID="textBox" runat="server" AutoPostBack="true" OnTextChanged="textChanged" CausesValidation="true" ValidationGroup="valGroup"></asp:TextBox>
<asp:RegularExpressionValidator ID="regEx" runat="server" ControlToValidate="textBox" ValidationGroup="valGroup" ErrorMessage="Not a valid number." Display="Dynamic" ValidationExpression="(^0*[1-9]+\d*(\.\d+)?$)|(^0*\.0*[1-9]+\d*$)" />
<asp:Button ID="btnSave" runat="server" Text="Save" OnClick="btnSaveClick" ValidationGroup="valGroup" />
<asp:Button ID="btnCancel" runat="server" Text="Cancel" OnClick="btnCancelClick" CausesValidation="false" />
It's a text box with a regular expression validator that's supposed to restrict the input to be only positive real numbers. When the text changes and it passes validation a textChanged() function is called.
If the text is invalid, textChanged() won't fire, and the save button won't work as well.
This works as intended.
I've also got a cancel button, and it's supposed to just clear the text box (and some other things server side). It should be able post back to the server whether or not the text box is valid, hence the CausesValidation="false" tag.
My problem is that when I enter something invalid into the text box, and then click cancel it actually executes textChanged() before btnCancelClick(). Even though it isn't valid.
This is a huge problem because textChanged() uses the text box text as a number, so the page throws an exception.
I have no idea what's causing textChanged() to be called. For one thing, the cancel button doesn't even call that function. And the regular expression validator should prevent the text box from calling it.
Edit: I've tried making some changes and experimenting.
function cancel()
{
document.getElementById('<%=textBox.ClientID%>').value = "";
}
<asp:Button ID="btnCancel" runat="server" Text="Cancel" OnClientClick="cancel()" CausesValidation="false" />
I switched the cancel button to call a JavaScript method to try to clear the text box. The results are kind of interesting.
When an invalid string is entered as the first thing, then the cancel button works fine. It clears the text box without textChanged() being called.
If I type in a valid number, textChanged() is called as I expect. But when I click the cancel button it does call cancel(), and immediately after that it calls textChanged() again, but now the text box is empty, leading to an exception.
A similar thing happens if I enter something valid, and then make it invalid. textChanged() is called for the valid input. When the incorrect input is added, the validator prevents textChanged() from being called. But when I click cancel it goes from cancel() to textChanged().
I was thinking that maybe it was because validators don't persist through postback, but with the JavaScript function cancel() the button can't cause the page to postback. textChanged() has to be what's causing it, but I have no idea how.
Edit 2: I'm not going to mark this solved, since it's still a huge problem in my opinion, but I have found a workaround.
<script>
function cancel() {
document.getElementById('<%=textBox.ClientID%>').value = "";
return false;
}
</script>
<asp:Button ID="btnCancel" runat="server" Text="Cancel" OnClientClick="return cancel();" CausesValidation="false" />
This doesn't allow the button to cause a postback under any circumstances. It's fixing something that shouldn't be there in the first place, but there it is.
This helps with the button click, but not with other things. I've got a GridView with an OnSelectedIndexChanged function server-side. It also causes the page to post back with the textChanged() function. I could try to create a JavaScript version of the GridView function and fix it like the cancel button, but at this stage I'll probably remove the OnTextChanged event handler and put the textChanged() function and put it behind a button.
add causesvalidation="true" works for me on the textbox control.
So close... What's needed is simply setting a dedicated name to the ValidationGroup name on the Cancel button. This will cause it to be processed out of cycle with the rest of the validation. Not setting it effectively puts it in the "default" validation group which behaves (as you've seen), a bit oddly.
To allow the Cancel button to be exempt from the rest of the form validation, the rule I generally apply is [ValidationGroupName]Cancel to ensure it's triggered outside that block of validation. In this case, setting the Cancel button to something like;
<asp:Button ID="btnCancel" runat="server" Text="Cancel" ValidationGroup="valGroupCancel" OnClick="btnCancelClick" />
Should give you your expected behaviour.
Related
I have an asp.net web form with several textboxes, buttons, and other controls. One of the buttons is supposed to trigger validation of content in some of the textboxes. This works fine, except that if validation fails, all subsequent postbacks of the page are prevented. Fixing the invalid values gets rid of the error messages, but postback still does not occur.
The validation is occurring within an AJAX UpdatePanel. I'm not sure if that matters or not.
I'm glad the workaround is fine for you, but for the benefit of others who land this page, disabling client side validation is far from an acceptable solution. So here goes:
Why it happened only when UpdatePanel was around, is still unclear to me, however:
As others have mentioned, the issue you were having is most likely because the unsuccessful validation attempt is preventing a further postback.
See also: Why won't my form post back after validation?
There is a variable called Page_BlockSubmit which is set to true when client side validation fails:
function Page_ClientValidate(validationGroup) {
....
Page_BlockSubmit = !Page_IsValid;
return Page_IsValid;
}
So when a __doPostBack occurs as part of, say, an OnSelectedIndexChanged of a DropDownList, there is this check:
function ValidatorCommonOnSubmit() {
....
var result = !Page_BlockSubmit; /* read the value */
....
Page_BlockSubmit = false; /* reset it */
return result;
}
Which will block the first time, but then clear the flag, so the next postback attempt should work.
The workaround, in my case, for a DropDownList's OnSelectedIndexChanged event, was to have a snippet added to its client-side onchange event:
<asp:DropDownList runat="server" ID="SomeDropDownList" OnSelectedIndexChanged="AlwaysDoSomething"
onchange="resetValidationState(this);">
....
</asp:DropDownList>
<script type="text/javascript">
function resetValidationState() {
// clear any postback blocks, which occur after validation fails:
window.Page_BlockSubmit = false;
}
</script>
You might get away with putting that snippet into the onchange itself.
except that after this button has been clicked no other button can cause a postback unless the validation errors have been corrected. So, btnDelete, which should not require validation of the textboxes, cannot postback until the textbox values are corrected
Don't see that behavior with following code..
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="RequiredFieldValidator" ControlToValidate="TextBox1" ValidationGroup="pc">
</asp:RequiredFieldValidator>
<asp:Button runat="server" ID="btnSubmit" Text="Submit" Width="150" CausesValidation="true" ValidationGroup="pc" />
<asp:Button runat="server" ID="btnDelete" Text="Delete" CausesValidation="false" />
I could be totally off base here - but i think I see the problem. (I work mainly with devexpress controls so the rules can be a bit different). When validation fails, the whole page is set to invalid, so no postbacks can occur. Can it be since the delete button is not causing any validation, its not re validating after those editors have been changed to be valid?
I have run into the same problem as described here.
Only the question is marked as answered with only an explanation as to why you may have to click twice when using a RequiredFieldValidator on input fields - once as the blur of a textbox(for example) will correct the validation and then again to actually post the form.
I don't want to have to click a button twice! Does anyone know a solution or workaround to this?
You could add EnableClientScript=false to the validator.
That prevents the client-side validation, so you will always get a postback (which may not exactly be what you want, though). The validation will still be done, just server-side.
Be sure to wrap the button-click logic in a if (Page.IsValid) { ... }, to check the status of the validators.
Apologies for not posting code previously I assumed this to be a standard problem with the RequiredFieldValidator, but have since realised my particular problem was coming from a CompareValidator, used to ensure entered passwords matched.
The CompareValidator was causing the issue that I described, causing me to have to click away from the field to blur and validate, before being able to click on the post button.
I'm not sure why but changing the Display of the CompareValidator from Dynamic to Static has cleared the problem up.
If the validator is Display="Dynamic", and the appearance of the error message causes the submit button to move, then the MouseUp event is not received by the submit button. In this case, the validation fires and clears the error message, but the submit button does not fire. To solve the problem, either set the the validators to be Display="Static", or rearrange the form so that the submit button does not move when error messages appear.
Here's a way to reserve about one, vertical line of space for a dynamic validation message:
<div style="height:1.5em;overflow:visible;">
<asp:RequiredFieldValidator ID="R1" runat="server"
ErrorMessage="Name is required" ControlToValidate="TextBoxName"
Display="Dynamic"></asp:RequiredFieldValidator>
</div>
I did not find it necessary to set EnableClientScript="false", although that did help for a CustomValidator that had no client-side validation function implemented.
Posting your code is always a good idea, That way we could run your code in a test environment and modify it to ensure it works before posting our answer.
I would suggest adding
causesValidation="true"
to your button to see if that works.
I have a better idea.
Add Text="" to textbox Control.
Add InitialValue="" to Validator Control.
What it will do, when it will be posting, it will find the value of the text box is still the initail value and it will throw an error and the form will not be posted.
Try this:
<asp:RequiredFieldValidator ID="reqFieldCloseComment" ControlToValidate="tbCloseComment" ValidationGroup="ChangeStatus" ErrorMessage="Please enter a reason" Display="Dynamic" runat="server" InitialValue=""></asp:RequiredFieldValidator>
<asp:TextBox ID="tbCloseComment" runat="server" CausesValidation="true" TextMode="MultiLine" Height="107px" Width="400px" Text=""></asp:TextBox>
<asp:Button ID="btnCloseRequestFinal" Text="Finish" CssClass="CloseReqButton" runat="server" ValidationGroup="ChangeStatus" />
Here is code that is working fine for me and helping to get rid of double click.
<asp:TextBox ID="TextBox1" runat="server" autocomplete="off"
Enabled="true" MaxLength="20" onfocus="SetActiveControl(this);" Text=""
CausesValidation="true" />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" ControlToValidate="TextBox1" Display="Static" ErrorMessage="Ha!" SetFocusOnError="True" EnableClientScript="true" ForeColor="" InitialValue="" />
$(function() {
$("input.btn").on("click",function(){
if(Page_BlockSubmit == true) {Page_BlockSubmit = false};
})
});
Page_BlockSubmit is a JS variable defined by the js generated from code behind when you define the validator . I haven't went deeper to know why MS need this variable, but the scenario is:
the first click will make Page_BlockSubmit become false.
the second click will check the value of Page_BlockSubmit and return true.
if you implemented the code I posted, every time you click the button, the variable will be set as false which will trigger the submit at every click.
And, you can use google chrome to trace the value of Page_BlockSubmit.
I have a simple web form with a textbox and a RequiredFieldValidator wired up to it. When the RequiredFieldValidator error is triggered the user has to click the submit twice to post the form. The first click clears the error, the second actually fires off the button click event. Is this expected behavior?
<asp:RequiredFieldValidator ID="reqFieldCloseComment" ControlToValidate="tbCloseComment" ValidationGroup="ChangeStatus" ErrorMessage="Please enter a reason" Display="Dynamic" runat="server"></asp:RequiredFieldValidator>
<asp:TextBox ID="tbCloseComment" runat="server" CausesValidation="true" TextMode="MultiLine" Height="107px" Width="400px"></asp:TextBox>
<asp:Button ID="btnCloseRequestFinal" Text="Finish" CssClass="CloseReqButton" runat="server" ValidationGroup="ChangeStatus" />
I tried adding CausesValidation to the textbox per a suggestion found from a Google search and it doesn't help.
EDIT It seems that it doesn't always have to be a double click to fire off the event. As long as text is entered into the textbox and then the focus is taken away from the textbox, the RequiredFieldValidator error message goes away and the form requires only a single click.
I had the same issue with a CompareValidator and found the problem went away when I changed the Display property from Dynamic to Static. Hope that helps
This happens because the code that clears out the error message runs when the textbox loses focus. So what happens is:
You enter text in the field
You click on the button, which causes the onblur event to happen on the textbox, firing the code to check the field's value again and removing the error message
Now there are no errors in validation, so clicking the button again submits the form.
When you press the tab key first (or basically do anything that takes the focus off the textbox), then that onblur script runs and clears out the error so that when you click the submit button it is ready to go.
I have an ASP.NET form with a few controls and a submit button at the bottom, all inside an update panel:
<asp:UpdatePanel runat="server" ID="upContent">
<ContentTemplate>
<asp:TextBox runat="server" ID="tbxMyTextBox" AutoPostBack="true" />
<asp:Button ID="btnSubmit" runat="server" Text="Submit" OnClientClick="return doStuff()" OnClick="btnSubmit_Click" />
</ContentTemplate>
</asp:UpdatePanel>
If I write something in the TextBox and click 'submit' immediately (without clicking out of the TextBox first), the changes are not recorded (as seen in the server-side event handler). However, if I write something in the TextBox, and then change focus to another control, an AutoPostback happens through the UpdatePanel and then clicking 'submit' does recognize these changes. How can I force this content to update right as I click the submit button, while still running both the clientside and serverside events attached to it? Thanks!
Is is possible that your text-box gets cleared due to some on-submit/on-click event handler? I will suggest you do use some tool such as Fiddler to inspect the POST data in request. Or you can put a break-point at your server side code and inspect the request data. Look for particularly Request.Form[tbxMyTextBox.UniqueID] - i.e. look for presence of value for your text-box's name (name property at client side which corresponds to UniqueID property at server side). If the request contains the value typed in the text-box then something is happening on server side but good news is you can always retrieve the value from Request object. If the value is not present in the Request object then it means that client side code is clearing the value before the submit.
If an onclick method returns false, it cancels the action that the button would normally perform. As your button would normally submit your form, but it appears not to be submitting, your client side javascript code in doStuff is probably returning false.
I have a ASP.NET Website, where, in a GridView item template, automatically populated by a LinqDataSource, there is a LinkButton defined as follows:
<asp:LinkButton ID="RemoveLinkButton" runat="server" CommandName="Remove"
CommandArgument='<%# DataBinder.GetPropertyValue(GetDataItem(), "Id")%>'
OnCommand="removeVeto_OnClick"
OnClientClick='return confirm("Are you sure?");'
Text="Remove Entry" />
This works fine. Whenever the Button is Clicked, a confirmation dialog is displayed.
What I am trying to do now, is to allow the user to enter a reason for the removal, and pass this on the the OnClick event handler. How would I do this?
I tried OnClientClick='return prompt("Enter your reason!");', but, of course, that did not work =)
Personally, I would stash the reason into a hidden field.
It would work something along these lines: your OnClientClick method would take the return value of a JS method, which does the prompt, and then places the result of the prompt into the hidden field.
You can also look into calling __doPostBack from your client-side code instead of using the OnClick postback. Then you can capture the reason and pass it server-side.