Ignore .NET validators if element is hidden (display: none) - javascript

We often come into problems with .NET validators on elements that are hidden using javascript/css (ie. display:none)
For example (there may be syntax errors but don't worry about it)
<asp:CheckBox ID="chkNewsletter" runat="server" Checked="true" />
...
<div id='newsletterOnly'>
<asp:TextBox ID="txtEmail" runat="server" />
<asp:RequiredFieldValidator ID="vldEmail" ControlToValidate="txtEmail" ErrorMessage="Required" runat="server" />
</div>
with JavaScript:
$('#chkNewsletter').changed(function() {
$(this).is(':checked') ? $('#newsletterOnly').show() : $('#newsletterOnly').hide();
});
It should not validate txtEmail if it is hidden.
You can't submit the form if newsletterOnly is hidden, because the RequiredFieldValidator is still effective eventhough it is hidden :(
And you can't even see the validator error message because it is hidden
Is there any way around this?
I am trying to avoid PostBacks to improve user experience.
I wish I could modify .NET javascript to validate controls only when they are visible.

I wrote this as a general solution (can be used on all .NET websites).
You only need to add an OnClientClick to the submit button.
//===================================================================
// Disable .NET validators for hidden elements. Returns whether Page is now valid.
// Usage:
// <asp:Button ID="btnSubmit" runat="server" Text="Submit" OnClientClick="DisableHiddenValidators()" />
//===================================================================
function DisableHiddenValidators() {
for (var i = 0; i < Page_Validators.length; i++) {
var visible = $('#' + Page_Validators[i].controltovalidate).is(':visible');
ValidatorEnable(Page_Validators[i], visible)
}
return Page_ClientValidate();
}
To use it, simply include the above javascript and add the class OnClientClick="DisableHiddenValidators()" to the submit button:
<asp:Button ID="btnSubmit" runat="server" Text="Submit" OnClientClick="DisableHiddenValidators()" />
EDIT:
jQuery $(submitButton).click function didn't work on iPhone/Android. I have changed the sample code above slightly.
If anyone see anything wrong or possible improvements please comment :)

It can also be a good idea to use Validation Groups in a situation like this. If you can group your validators then specify on the Button which validation group you need to validate against, only those validators in the group will be validated. Read more here:
http://msdn.microsoft.com/en-us/library/vstudio/ms227424(v=vs.100).aspx

Magic: Thankyou!
Modified slightly to include the ValidationGroup it resides in..
function DisableHiddenValidators(validationGroup) {
for (var i = 0; i < Page_Validators.length; i++) {
var isVisible = $('#' + Page_Validators[i].controltovalidate).is(':visible');
var isValGrp = (Page_Validators[i].validationGroup === validationGroup);
ValidatorEnable(Page_Validators[i], (isValGrp && isVisible)); //Turn on only if in Validation group and IsVisible = true
}
return Page_ClientValidate(validationGroup);
}
To add Custom DisableValidators method to the click event tree:
$('#myButtonControlId').on("click", function(e) { DisableHiddenValidators('Send'); });

Related

ASP.Net LinkButton Prevent Postback Not Working - JavaScript

I know how to prevent javscript within the href attribute from firing as evident in this JSFiddle (http://jsfiddle.net/mkarr/KNefK/)
However, when this logic is applied to an ASP.Net LinkButton as such:
<asp:LinkButton ID="btnSubmit" runat="server" Text="Submit" OnClientClick="return formTest.validate(event);" OnClick="btnSubmit_Click"></asp:LinkButton>
which translates to:
<a onclick="return formTest.validate(event);" id="ctl00_m_g_87932399_e546_4e12_8297_982b811d8cea_ctl00_btnSubmit" href="javascript:WebForm_DoPostBackWithOptions('blah blah blah')">Submit</a>
The formTest.validate() method does execute correctly and returns false, but the WebForm_DoPostBackWithOptions is always fired immediately after!
Can anyone see any flaws in my logic that I cannot??
EDIT:
Also, several stack overflow solutions have been accepted for this issue but all of them are doing virtually what I have already done leading me to believe I'm missing something simple!
Disable the postback on an <ASP:LinkButton>
Prevent LinkButton post back OnClientClick not working. Why?
ANSWER:
Since I cannot answer my own question because I'm not reputable yet (LOL), here's an edit with the answer:
Going off #QBM5's original tip of not using ASP.Net controls, I solve the problem, although I still do not know why the initial problem occurred in the first place (does anyone when it comes to ASP.Net? Turn it off, then back on comes to mind here) :o)
I replaced the LinkButton ASP.Net control with the following:
<input type="submit" value="Submit" id="btnSubmitButton" runat="server" OnServerClick="btnSubmitButton_Click" class="submitBtn" />
I then bound the .submitBtn's click event via jQuery:
$('.submitBtn').on('click', function (e) {
if (!instance.validate()) {
e.preventDefault();
}
});
The trick is to use OnServerClick and runat="server" on the control but getting away from LinkButton was the goal and the postback behavior is completely different.
which translates to this:
<input onclick="if (typeof(Page_ClientValidate) == 'function') Page_ClientValidate(''); " type="submit" id="ctl00_m_g_87932399_e546_4e12_8297_982b811d8cea_ctl00_btnSubmitButton" value="Submit" class="submitBtn">
Anyone want to take a stab at the root cause? I need to move foward so don't have time. :o)
The following is working for me, by changing element.href = "#"
<asp:LinkButton ID="btnSubmit" runat="server" Text="Submit" OnClientClick="return ClientSideValidation()" OnClick="btnSubmit_Click"></asp:LinkButton>
Javascript validation
function ClientSideValidation() {
var element = document.getElementById("<%=txtAmount.ClientID%>");
element.href = "";
if (element.value == "") {
element.href = "#";
return false;
}
return true;
}

vb .net, javascript issue involving strict mode

I have a VB .net application that I am attempting to integrate with a former deverlopers code.
The code takes a zipcode and returns a list of stores, along with their location on a google map canvas.
The process works great, with one exception.
I get the following error
JavaScript runtime error: Accessing the 'caller' property of a
function or arguments object is not allowed in strict mode.
I have isolated the culprit to
__doPostBack('userControlSearchResults_results', LatLng);
Which internally has the following
function Sys$WebForms$PageRequestManager$_doPostBack(eventTarget, eventArgument) {
var event = window.event;
if (!event) {
var caller = arguments.callee ? arguments.callee.caller : null;
if (caller) {
var recursionLimit = 30;
while (caller.arguments.callee.caller && --recursionLimit) {
caller = caller.arguments.callee.caller; // ERRORS HERE
}
event = (recursionLimit && caller.arguments.length) ? caller.arguments[0] : null;
}
}
...
My first inclination was to create a window.event so it by passes the if(!event) and moves on.
Since, there are other times we call __doPostback in the code and it is successful.
However since my JavaScript is limited, i am either doing it wrong or need to find a different approach.
I have searched for this problem and very little has come back. The common response is to just comment out the 'use strict'; and move on.
The problem is we pull in a lot of JavaScript libraries and many of them are now set to 'use strict'
Does anyone have a suggestion or an idea on how to address this?
A blog made reference to trying to apply a setTimeout() before the __doPostback call.
However I do not see how that would resolve anything.
Edit: Added some more code.
__doPostback is within the following javascript
function CompleteSearch(returnedLatLng) {
if (returnedLatLng != '') {
alert("dopostback here2- this is where it breaks");
__doPostBack('ucSearchResults_udpResults', returnedLatLng);
if (document.getElementById("sidebar_search")) { document.getElementById("sidebar_search").style.display = "none" };
if (document.getElementById("sidebar_login")) { document.getElementById("sidebar_login").style.display = "none" };
if (document.getElementById("promo1")) { document.getElementById("promo1").style.display = "none" };
document.getElementById("sidebar_results").style.display = "block";
//document.getElementById("sidebar_results").style.display = "none";
}
return false;
}
Where as my update panel is within a user control and looks like this...
<form id="Form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<div id="Container" style="zoom:1" onclick="">
<asp:UpdatePanel runat="server" ID="udpResults" OnLoad="UpdatePanel1_Load">
<ContentTemplate>
<asp:HiddenField ID="currentLatLong" runat="server" />
<asp:HiddenField ID="triggerSearch" runat="server" Value="0" />
<asp:HiddenField ID="searchString" runat="server" Value="0" />
<asp:HiddenField ID="locationCode" runat="server" />
<asp:HiddenField ID="locationDesc" runat="server" />
<asp:HiddenField ID="locationPhone" runat="server" />
<asp:HiddenField ID="locationZip" runat="server" />
<asp:HiddenField ID="filterPickup" runat="server" />
<asp:HiddenField ID="filterVirtualKiosk" runat="server" />
<asp:HiddenField ID="filterDelivery" runat="server" />
<asp:HiddenField ID="filterAcceptsCash" runat="server" />
<asp:HiddenField ID="filterKey2Key" runat="server" />
<asp:HiddenField ID="filterHODService" runat="server" />
<asp:Label ID="tblResults" runat="server"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
Does this help or would more code be required.
I am really stuck right now and do not know where to proceed.
This problem occurs when window.event contains null.
I found that it contains null on a JavaScript timer event only.
Maybe it contains null on some other special events too.
There are 2 solutions.
Solution A:
1/ on the timer event: rise an user interface element event like click
2/ on an event handler for this element event: call __doPostBack
There is still a trap.
You may think that you can create an event objet and fire it on an element.
This would work, but window.event would still contain null.
It looks strange, but I suppose it is by design.
The only way to trigger an element event AND having window.event containing the event instead of null is to call this element click method.
Solution B:
If the UpdatePanel contains an input type="submit" element, there is no need to call __doPostBack to perform an asynchronous postback.
Calling this element click method is enought.
If the UpdatePanel contains no input submit element, the timer event handler can create one and use it:
var btn = document.createElement('INPUT');
btn.setAttribute('name', 'timer_dummy_button');
btn.setAttribute('type', 'submit');
btn.setAttribute('value', 'what you like');
btn.setAttribute('style', 'display:none;');
document.getElementById('yourNiceLittleUpdatePanelID').appendChild(btn);
btn.click();
On asynchronous postback, Page.Request.Form would contain these items :
["yourNiceLittleScriptManagerControlID"] = "yourNiceLittleUpdatePanelID|timer_dummy_button"
["__EVENTTARGET"] = ""
["__EVENTARGUMENT"] = ""
["timer_dummy_button"] = "what you like"
I don't think this Sys$WebForms$PageRequestManager$_doPostBack javascript code was done by any developer, I think that it's the ASP engine generates it. I think you should post the ASP code, maybe this userControlSearchResults_results function's code.
There are many posts on how to use __doPostBack. Check that you use it properly.
How to use __doPostBack()

Set enter key behavior on aspx form

Have the need to alter the behavior of pressing enter on my aspx page based on the last control that was interacted with. I have two textboxes and a dropdown. Each one of those controls has a corresponding button that takes the input and applies it to other fields on the page. Much like adding options to a master part.
Example: If button2 is pressed, the option in textbox2 would be applied, but not the option in textbox1, or the dropdown. The page is refreshed, and the user can continue to select options.
How would I alter the page to allow the user to type in text in a textbox and then hit enter to activate the code for the corresponding button. I've tried various js to set the page default, but have been unsuccesseful in changing this on the fly.
You can use ASP.Net Panel control's DefaultButton to accept enter key.
http://geekswithblogs.net/ranganh/archive/2006/04/12/74951.aspx
<asp:Panel ID="pnl1" runat="server" defaultbutton="Button1">
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button1" OnClick="Button1_Click" />
</asp:Panel>
<asp:Panel ID="pnl2" runat="server" defaultbutton="Button2">
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:Button ID="Button2" runat="server" Text="Button2" OnClick="Button2_Click" />
</asp:Panel>
Set event listeners for a user modifying the inputs and set a reference to the proper button. Then have a listener for the enter button to trigger submitting the referenced button. You didn't mention jQuery or any JS framework so I'll try writing it generally for plain javascript, I'd recommend using a framework though for cross browser support.
var myButtonId = null;
var storeInputButtonId = function(buttonId) {
return function(event) {
myButtonId = buttonId;
};
};
//Do following for inputs, or your preferred event binding pattern
var fld = document.getElementById('myInputId');
//Statically refer to button id or replace with suitable algorithm
var inputButtonId = "";
if (fld.addEventListener) {
//Could bind to other events with logic based on input element type
fld.addEventListener('keyup',storeInputButtonId(inputButtonId), false);
}
//Method to trigger the button click event
function submitData(event){
//Watch for the enter button
if ( event.which == 13 ){
document.getElementById(myButtonId).click();
}
}
//Bind the listener to the enter button
var bodyElement = document.getElementsByTagName('body')[0];
if (bodyElement.addEventListener) {
bodyElement.addEventListener('keydown',submitData, false);
}

Can I run some custom script after ASP.NET client side page validation fails?

I'm trying to run some client side script if, and only if, the client side Page validation fails, and can't figure out where I can hook it in.
If i bind my JavaScript function to the OnClientClick of the button that submits the form, it runs before the client side validation. If I bind it to the OnSubmit of the form, that only fires if the validation passes.
Any ideas of how or where I can hook something like this up? Or if you have other suggestions, I'm open to them.
<form id="frm" runat="server"
onsubmit="FUNCTION HERE WONT FIRE IF VALIDATION FAILS">
<asp:requiredfieldvalidator id="vld" runat="server" controltovalidate="txt"/>
<asp:textbox id="txt" runat="server"></asp:textbox>
<asp:button id="cmd" runat="server" OnClick="dosomething"
OnClientClick="FUNCTION FIRES BEFORE VALIDATION OCCURS">
</form>
Add script below at the end of page's markup file:
var originalValidationFunction = Page_ClientValidate;
if (originalValidationFunction && typeof (originalValidationFunction) == "function") {
Page_ClientValidate = function (validationGroup) {
originalValidationFunction(validationGroup);
if (!Page_IsValid) {
// your code here
alert("oops!");
}
};
}
Try using Page_ClientValidate("") to trigger validation from JavaScript, and then you can run some custom code:
validate = function(){
var isValid = Page_ClientValidate(""); //parameter is the validation group - thanks #Jeff
if (isValid){
isValid = somethingToCheck();
}
return isValid;
}
<asp:Button ID="Button1" runat="server" CausesValidation="false" OnClientClick="return validate();" ... />
So you have two options how to handle it:
Use CustomValidator validator which provides ClientValidationFunction feature and inside your custom validation function obviously you know whether validation failed. It gives you as much as you need flexibility on client side validation by accepting a JavaScript function to be used whilst validation.
Check validator satus by accessing it via JavaScript by accessing validator's isValid property from JavaScript (+jQuery):
var anonymousValidator = $("#<%= vldCommentText.ClientID %>")[0];
ValidatorEnable(anonymousValidator, true);
if (!anonymousValidator.isvalid)
{
// ...
}

Enabling Disabling button asp .net - using javascript

Currently in my application I am having a button and a text box. The user types something in the textbox and then presses the button. What I want is that:
The search button should should stay disabled when the page loads for the first time. I can achieve that by setting it to disabled in the code behind file.
Now I want it to remain disabled when the user types upto 2 characters. The moment the user types third character the button should get enabled automatically.
The important thing is that it has to be done without asp .net AJAX since this website will be run from old mobile phones. So only pretty basic javascript or jquery is supported.
Any help will be appreciated.
Thanks
Varun
in order to use the document.getElementById in asp.net and not have to use the full name, you should let asp.net provide it. Instead of:
document.getElementById("ctl00_ctl00_phContent_phPageContent_btnSearch")
Try:
document.getElementById('<%= btnName.ClientID %>')
Where btnName is the asp:Button Id. The <%= code will generate the actual button id, fully qualified, so you don't have to worry about things changing with the hard coded id.
I got this to work with a HTML text box, I don't think you can do it with a asp.net text box:
<head>
<script type="text/javascript">
function TextChange() {
var t = document.getElementById("Text1");
var b = document.getElementById("Button1");
if (t.value.length > 2) {
b.disabled = false;
}
else {
b.disabled = true;
}
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<input id="Text1" type="text" onkeyup="TextChange();" />
<asp:Button ID="Button1" runat="server" Text="Button" Enabled="False" />
</div>
</form>
</body>
If you're using jQuery, use
$(<selector>).val().length
to get the size, then you can set the button's disabled attribute with
$(<button selector>).attr('disabled',false).

Categories

Resources