first of all apologies for my english.
I'm a newby in json area.
My problem is that i can't parse the data recived in a json response into a asp:LinkButton or whatever asp:element, coz i can't create a correct sintax.
Especifically, What I'm trying to do, is this:
<script type="text/javascript">
$.getJSON("http://www.carqueryapi.com/api/0.3/?callback=?", { cmd: "getMakes", min_year:"1941", max_year:"2012"}, function (data) {
var makes = data.Makes;
for (var i = 0; i < makes.length; i++) {
($("<asp:LinkButton ID=\"lb" + i +"\" runat=\"server\" />").text(makes[i].make_display )).appendTo("#lbProva");
}
});
<script>
<ul id="lbProva" class="lb_prova" >
</ul>
I hope that someone could help me coz i've tryed many possibilities but no one was the right one.
Thank u in advance.
You can't create asp.net server controls in javascript on client side. If you want to use json data on client side, you must apply it to already generated html controls.
Actually, you can create server controls only on a server. So the question is how to pass AJAX call response to server and enforce it to refresh desired area on a page.
First variant
<script type="text/javascript">
$(function () {
$.getJSON("http://www.carqueryapi.com/api/0.3/?callback=?", { cmd: "getMakes", year: "2009" },
function (data) {
//The 'data' variable contains all response data.
var makes = $.map(data.Makes, function (make) { return make.make_display; }).join(";");
document.getElementById("<%= CarMakersHiddenField.ClientID %>").value = makes;
__doPostBack("<%= CarMakersUpdatePanel.ClientID %>", "");
});
});
</script>
<asp:UpdatePanel runat="server" ID="CarMakersUpdatePanel" UpdateMode="Conditional">
<ContentTemplate>
<asp:HiddenField runat="server" ID="CarMakersHiddenField" />
<asp:BulletedList runat="server" ID="MakersList" DisplayMode="LinkButton">
</asp:BulletedList>
</ContentTemplate>
</asp:UpdatePanel>
Server code:
protected void Page_Load(object sender, EventArgs e)
{
MakersList.Items.Clear();
foreach (var maker in CarMakersHiddenField.Value.Split(';'))
{
MakersList.Items.Add(maker);
}
}
Second approach is more siutable if you need to pass to server some complex object like array of makers objects. In that case you can serialize this object to JSON string on client and deserialize it on server. Looks like previous version with bit changes:
<script type="text/javascript">
$(function () {
$.getJSON("http://www.carqueryapi.com/api/0.3/?callback=?", { cmd: "getMakes", year: "2009" },
function (data) {
//The 'data' variable contains all response data.
var serializedString = Sys.Serialization.JavaScriptSerializer.serialize(data.Makes);
document.getElementById("<%= CarMakersHiddenField.ClientID %>").value = serializedString;
__doPostBack("<%= CarMakersUpdatePanel.ClientID %>", "");
});
});
</script>
Markup left the same as in the first version.
Server code:
[Serializable]
public class Make
{
public string make_id;
public string make_display;
public bool make_is_common;
public string make_country;
}
protected void Page_Load(object sender, EventArgs e)
{
MakersList.Items.Clear();
if (!String.IsNullOrEmpty(CarMakersHiddenField.Value))
{
var serializer = new DataContractJsonSerializer(typeof(Make[]));
using (var stream = new MemoryStream(Encoding.Unicode.GetBytes(CarMakersHiddenField.Value)))
{
var makes = serializer.ReadObject(stream) as Make[];
if (makes != null)
{
foreach (var maker in makes)
{
MakersList.Items.Add(new ListItem(maker.make_display, maker.make_id));
}
}
}
}
}
Related
I am using Ajax to call some method from database
this method takes parameters from the page
and gets some values from the DB
I want to populate the result to the page controls by accessing these controls in the web method.
Below is my code. I am using collapsible panel extender. On click event it collapses & should call verifyFunction method written in code behind.
<asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server" EnablePageMethods="True"></asp:ToolkitScriptManager>
<asp:Panel ID="Panel1" runat="server">
</asp:Panel>
<asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
<asp:CollapsiblePanelExtender ID="cpeSOP" runat="Server" CollapseControlID="LinkButton1"
CollapsedSize="0" Collapsed="True" CollapsedImage="~/imgages/addRow.gif"
ExpandControlID="LinkButton1" ExpandDirection="Vertical" ExpandedImage="~/imgages/addRow.gif"
ImageControlID="Image1" SuppressPostBack="true" TargetControlID="Panel1">
<!-- JAVASCRIPT CONTENT -->
<script type="text/javascript">
function pageLoad(sender,args){
$find("collapsibleBehavior").add_expandComplete( expandHandler );
$find("collapsibleBehavior").add_collapseComplete( collapseHandler );
}
function expandHandler( sender , args ){
alert('I have expanded');
// NewPlanBudget.aspx/verifyFunction
$.ajax(
{
url: "NewPlanBudget.aspx/verifyFunction",
data: "flag=1",
success: function (msg) {
if (msg.d) {
alert("Sucess");
}
}
});
}
function collapseHandler( sender , args ){
alert('I have collapsed');
}
The code behind is
[WebMethod]
protected void Page_Load(object sender, EventArgs e)
{
cpeSOP.BehaviorID = "collapsibleBehavior";
}
public static void verifyFunction()
{
LinkButton1.Text = "Hello";
}
i think you cannot access page controls in web method but you can return the results to ajax and have to get the results
and also post your sample code, i dont know why are you calling page load in web-method,
and also the script must be
$.ajax(
{
url: "NewPlanBudget.aspx/verifyFunction",
data: {flag="1"},
success: function (msg) {
if (msg.d) {
alert("Sucess");
}
}
});
and you must get the value in web-method as
public static void verifyFunction(string flag)
{
}
and give name to link-button in design page itself
as
<asp:LinkButton ID="LinkButton1" Text="Hello" runat="server">LinkButton</asp:LinkButton>
public static void Savedata() {
if (HttpContext.Current != null) {
Page page = (Page)HttpContext.Current.Handler;
TextBox TextBox1 = (TextBox)page.FindControl("TextBox1");
}
}
I have an image box and a Photo Upload control with a Save button. I need to upload an image into the Image Box.
When I click the Upload button, it should show the Image in the Image Box.
When I click the Save button, the path of the uploaded image should be saved in the database.
My issue is the photo gets uploaded, but only after I click the Upload button for the second time.
P.S. I use a Client side function for uploading the photo.
Following are my codes.
CLIENT SIDE FUNCTION FOR UPLOADING THE PHOTO
function ajaxPhotoUpload() {
var FileFolder = $('#hdnPhotoFolder').val();
var fileToUpload = getNameFromPath($('#uplPhoto').val());
var filename = fileToUpload.substr(0, (fileToUpload.lastIndexOf('.')));
alert(filename);
if (checkFileExtension(fileToUpload)) {
var flag = true;
var counter = $('#hdnCountPhotos').val();
if (filename != "" && filename != null && FileFolder != "0") {
//Check duplicate file entry
for (var i = 1; i <= counter; i++) {
var hdnPhotoId = "#hdnPhotoId_" + i;
if ($(hdnPhotoId).length > 0) {
var mFileName = "#Image1_" + i;
if ($(mFileName).html() == filename) {
flag = false;
break;
}
}
}
if (flag == true) {
$("#loading").ajaxStart(function () {
$(this).show();
}).ajaxComplete(function () {
$(this).hide();
return false;
});
$.ajaxFileUpload({
url: 'FileUpload.ashx?id=' + FileFolder + '&Mainfolder=Photos' + '&parentfolder=Student',
secureuri: false,
fileElementId: 'uplPhoto',
dataType: 'json',
success: function (data, status) {
if (typeof (data.error) != 'undefined') {
if (data.error != '') {
alert(data.error);
} else {
$('#hdnFullPhotoPath').val(data.upfile);
$('#uplPhoto').val("");
$('#<%= lblPhotoName.ClientID%>').text('Photo uploaded successfully')
}
}
},
error: function (data, status, e) {
alert(e);
}
});
}
else {
alert('The photo ' + filename + ' already exists');
return false;
}
}
}
else {
alert('You can upload only jpg,jpeg,pdf,doc,docx,txt,zip,rar extensions files.');
}
return false;
}
PHOTO UPLOAD CONTROL WITH SAVE BUTTON AND IMAGE BOX
<table>
<tr>
<td>
<asp:Image ID="Image1" runat="server" Height="100px" Width="100px" ClientIDMode="Static" />
<asp:FileUpload ID="uplPhoto" runat="server" ClientIDMode="Static"/>
<asp:Label ID="lblPhotoName" runat="server" Text="" ForeColor ="Green" ClientIDMode="Static"></asp:Label>
<asp:Button id="btnSave" runat="server" Text="Upload Photograph" onClick="btnSave_Click" OnClientClick="return ajaxPhotoUpload();"/>
</td>
</tr>
</table>
SAVE BUTTON CLICK EVENT IN SERVER SIDE (to show the uploaded image in the image box)
Protected Sub btnSave_Click(sender As Object, e As EventArgs)
Image1.ImageUrl = hdnFullPhotoPath.Value
End Sub
I’d recommend that you drop client side AJAX upload via JS and stick to standard way of uploading. You can probably achieve the same effects without the excessive javascript.
If file type filtering is an issue you can check this post for more details.
Getting extension of the file in FileUpload Control
In either way you have to make a postback so it doesn’t really matter if you upload from JS or the server side except that second method is less complex.
Adding update panel will make this more user friendly and you should be all done.
<head runat="server">
<title>Index</title>
<script src="../../Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
<script src="../../Scripts/ajaxupload.js" type="text/javascript"></script>
</head>
<body>
<div>
<input type="button" id="uploadFile" value="Upload File" />(jpg|jpeg|png|gif)
<div id="uploadStatus" style="color: Red">
</div>
</div>
<script type="text/javascript" language="javascript">
new AjaxUpload('#uploadFile', {
action: 'Handler1.ashx',
name: 'upload',
onComplete: function (file, response) {
if (response == '0') {
$('#uploadStatus').html("File can not be upload.");
}
else {
$('#img').attr("src", "response.path");
}
},
onSubmit: function (file, ext) {
if (!(ext && /^(jpg|jpeg|png|gif)$/i.test(ext))) {
$('#uploadStatus').html("Invalid File Format..");
return false;
}
$('#uploadStatus').html("Uploading...");
}
});
</script>
Then create a handler for uploading image on server
public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string a = "1";
if (context.Request.Files != null && context.Request.Files.Count > 0)
{
if (context.Request.Files[0].ContentLength > 1000)
{
a = "0";
}
}
else
{
a = "0";
}
context.Response.Write(a);
context.Response.End();
}
public bool IsReusable
{
get
{
return false;
}
}
}
All, thanks for your time and help.! The tilde(~) symbol was the issue - the file's path wasn't recognized. So I modified my code to replace it with empty space.
var orgpath = data.upfile;
var photopath = orgpath.replace('~/', '');
$('#<%= ImgFacultyPhoto.ClientID%>').attr('src', photopath);
I have a requirement of adding server side variables in client side and other way round. Because I need to set a value from client side using javascript and access the same in code behind page.
I have to use C#.Net and javascript.
Any directions please
You can simply write out variables to the javascript using code blocks (<%%>):
var mJSVariable = <%:myServerSideVariable%>;
To do the opposite, the easiest thing it to write the JS value into a server side hidden form field and pick it up on the server side:
<input type="hidden" id="myHiddenId" runat="server" />
// Javascript
var myHidden = document.getElementById("<%:myHiddenId.ClientId%>");
myHidden.value = myJSVariable;
// Code behind
var myJSVariableValue = myHiddenId.Value;
you can declare some variable at server side .cs file like public int myServerSideINT and can access it on .aspx file using
<script type="text/javascript">
function getServerSideVAR()
{
var serverVAR=<%= this.myServerSideINT %>;
}
</script>
i hope this will helpful to you
The way I normally do it is via an ASP.NET HiddenField.
in JS you can set it via (JQuery example):
$("input[Name$='_IDofField']").val(<newvalue>);
On ASP.NET you can access it via the IDofField.Value property.
It is possible to store JavaScript variable values into server side variable. All you have to do is to implement System.Web.UI.ICallbackEventHandler class.
Below is the code demonstrating how to do it.
In aspx Page:
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Client Calback Example</title>
<script type="text/ecmascript">
function LookUpStock()
{
var lb=document.getElementById("tbxPassword");
var product=lb.value;
CallServer(product,"");
}
function ReceiveServerData(rValue){
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<input type="password" id="tbxPassword" />
<input type="Button" onclick="LookUpStock">Submit</button>
</div>
</form>
</body>
In Code Behind (CS) Page:
public partial class _Default : System.Web.UI.Page,System.Web.UI.ICallbackEventHandler
{
protected String returnValue;
protected void Page_Load(object sender, EventArgs e)
{
String cbReference = Page.ClientScript.GetCallbackEventReference
(this,"arg", "ReceiveServerData", "context");
String callbackScript;
callbackScript = "function CallServer(arg, context)" +
"{ " + cbReference + ";}";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
"CallServer", callbackScript, true);
}
public void RaiseCallbackEvent(String eventArgument)
{
if(eventArgument == null)
{
returnValue = "-1";
}
else
{
returnValue = eventArgument;
}
}
public String GetCallbackResult()
{
return returnValue;
}
}
Now you can get the JavaScript variable product value into Server side variable returnValue.
I have had a situation where a HiddenField was not usefull to pass a value from javascript to APS.net at serverside. My script was reading a value and then calling to code in server side but the value on hidden field was not updated yet on ASP.net hiddenfield control.
The only solution I've found was to write the value in a cookie with javascript and later read it on ASP.net page.
on javascript:
function setCookie(cname, cvalue, exdays, path) {
var d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toUTCString();
if (path != undefined)
expires += "; path=" + path;
document.cookie = cname + "=" + cvalue + "; " + expires;
}
setCookie("currentDbCompras", _currentDb);
and at server side
Request.Cookies("currentDbCompras").Value
I hope it helps!!!
I have an asp.net textbox like this:
<asp:TextBox ID="PINPad" runat="server" Columns="6" MaxLength="4"
CssClass="PINTextClass"></asp:TextBox>
It is, as you might have guessed, the text box from an on screen PIN pad. Javascript fills in the values. The page is posted back every five seconds (using an update panel if that matters) to update various other unrelated items on the screen. This works just fine.
However, when I convert it to a password text box, like this:
<asp:TextBox ID="PINPad" runat="server" Columns="6" MaxLength="4"
CssClass="PINTextClass" TextMode="Password"></asp:TextBox>
Then whenever the page posts back, the text box is cleared out on the screen and the textbox is empty (though during the timer event, the value does make it back to the server.)
Any suggestions how to fix this, so that it retains its value during postback?
As a security feature, ASP.NET tries to disallow you from sending the password value back to the client. If you're okay with the security issues (i.e. it's either not really secure information or you're sure that the connection is secure), you can manually set the "value" attribute of the control, rather than using its Text property. It might look something like this:
this.PINPad.Attributes.Add("value", this.PINPad.Text);
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
if (!(String.IsNullOrEmpty(txtPwd.Text.Trim())))
{
txtPwd.Attributes["value"]= txtPwd.Text;
}
if (!(String.IsNullOrEmpty(txtConfirmPwd.Text.Trim())))
{
txtConfirmPwd.Attributes["value"] = txtConfirmPwd.Text;
}
}
}
here is another way to do it:-
using System;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebControlLibrary
{
public class PWDTextBox : TextBox
{
public PWDTextBox()
{
this.TextMode = TextBoxMode.Password;
}
public string Password
{
get
{
string val = (string)ViewState["pwd"];
if (string.IsNullOrEmpty(val))
{
return "";
}
else
{
return val;
}
}
set
{
ViewState["pwd"] = value;
}
}
public override string Text
{
get
{
return Password;
}
set
{
Password = value;
}
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
this.Text = Password;
}
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Password);
}
}
}
The problem of losing the password in the postback can be avoid making use of Asynchronous JavaScript calls, lets describe a typical scenario for a Login page:
Lets say we have a Login page which allows the user to change the language of its labels when the user choose a language with a dropdownlist
a solution would be to invoke selectedIndexChanged event of the dropdownlist, make a postback which goes to the server and picks up the labels in the chosen language.
in this scenario the field password will be lost due to the security feature of ASP.NET which makes passwords fields not persisted between a postbacks.
This scenario can be solved if the postback is avoided making use of Asynchronous JavaScript Technology and XML (Ajax) calls.
Add a javascript function which will be invoked from the dropdownlist control, in this case this function is assigned to the Command property of the dropdownlist in code behind:
function ValueChanged(div)
{
var table = div.getElementsByTagName("table");
if (table && table.length > 0)
{
var t = table[0].getAttribute('type');
if (t != null && (t == "DropDown"))
{
var inputs = div.getElementsByTagName("input");
if (inputs && inputs.length == 2)
{
{
Translate(inputs[1].value);
}
}
}
}
}
The Translate function takes as parameter the selected option language in the dropdown control and performs the asynchronous call as shown bellow.
function Translate(lang)
{
var request = null;
if (window.XMLHttpRequest)
{
request = new XMLHttpRequest();
if (request.overrideMimeType)
{
request.overrideMimeType('text/xml');
}
}
else if (window.ActiveXObject)
{
request = new ActiveXObject("Msxml2.XMLHTTP");
}
if (request == null)
{
return;
}
var url = "GetLoginTranslations.aspx";
request.open('GET', url +'?lang=' + lang, true);
request.setRequestHeader("Cache-Control", "no-cache");
request.setRequestHeader("Pragma", "no-cache");
request.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
request.onreadystatechange = function () { TranslateLabels(request); };
request.send(null);
}
the function Translate shown above performs the call and get the results in the specified .aspx page (in this case "GetLoginTranslations.aspx")
when the request is completed and the request.onreadystatechange is set to the function TranslateLabels this function will be executed.
on this way the postback is not executed as before in the event onSelectedIndexChanged of the dropdownlist control.
the TranslateLabels function would look something like :
function TranslateLabels(request)
{
if (request.readyState == 4)
{
if (request.status == 200)
{
if (request.responseXML)
{
var objRoot = request.responseXML.documentElement;
if (objRoot)
{
if (objRoot.nodeName == "strings")
{
for (var i = 0; i < objRoot.childNodes.length; i++)
{
var node = objRoot.childNodes[i];
var elem;
switch (node.getAttribute("id"))
{
case "lbl_login":
elem = document.getElementById("lbl_login");
if (elem)
elem.innerHTML = node.firstChild.nodeValue;
break;
}
///....
}
}
}
}
}
}
the request.responseXML contains the XML built in the page GetLoginTranslations.aspx and the structure of this XML is defined there.
the Page_Load() event in the GetLoginTranslations.aspx should look like:
protected void Page_Load(object sender, EventArgs e)
{
if (Request["lang"] != null)
strLang = Request["lang"];
//init response
Response.Clear();
Response.Cache.SetExpires(DateTime.Now);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetValidUntilExpires(true);
Response.ContentType = "application/xml";
Response.Charset = "utf-8";
XmlTextWriter xml = new XmlTextWriter(Response.OutputStream, System.Text.Encoding.UTF8)
{
Formatting = Formatting.None
};
xml.WriteStartDocument();
xml.WriteStartElement("strings");
xml.WriteStartElement("string");
xml.WriteAttributeString("id", "lbl_login");
xml.WriteString(GetTranslation("label_login", strLang));
xml.WriteEndElement();
// ... the other labels
xml.WriteEndElement(); //</strings>
xml.Close();
}
Some other considerations:
set the the property AutoPostback of the dropdownlist to false.
Happens both for view-model properties named 'Password' and 'PIN'. You can bypass the behavior by defining those as:
string Password ;
... rather than:
string Password { get; set; }
If you do so, features such the 'LabelFor' macro displaying 'DisplayAttribute.Name' no longer works, so you'd have to define those directly in the HTML.
Or you can simply name the fields something other than 'Password' or 'PIN'.
How can I execute some javascript when a Required Field Validator attached to a textbox fails client-side validation? What I am trying to do is change the css class of the textbox, to make the textbox's border show red.
I am using webforms and I do have the jquery library available to me.
Here is quick and dirty thing (but it works!)
<form id="form1" runat="server">
<asp:TextBox ID="txtOne" runat="server" />
<asp:RequiredFieldValidator ID="rfv" runat="server"
ControlToValidate="txtOne" Text="SomeText 1" />
<asp:TextBox ID="txtTwo" runat="server" />
<asp:RequiredFieldValidator ID="rfv2" runat="server"
ControlToValidate="txtTwo" Text="SomeText 2" />
<asp:Button ID="btnOne" runat="server" OnClientClick="return BtnClick();"
Text="Click" CausesValidation="true" />
</form>
<script type="text/javascript">
function BtnClick() {
//var v1 = "#<%= rfv.ClientID %>";
//var v2 = "#<%= rfv2.ClientID %>";
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("background-color", "red");
}
}
}
return val;
}
</script>
You could use the following script:
<script>
$(function(){
if (typeof ValidatorUpdateDisplay != 'undefined') {
var originalValidatorUpdateDisplay = ValidatorUpdateDisplay;
ValidatorUpdateDisplay = function (val) {
if (!val.isvalid) {
$("#" + val.controltovalidate).css("border", "2px solid red");
}
originalValidatorUpdateDisplay(val);
}
}
});
</script>
This code decorates the original ValidatorUpdateDisplay function responsible for updating the display of your validators, updating the controltovalidate as necessary.
Hope this helps,
I think you would want to use a Custom Validator and then use the ClientValidationFunction... Unless it helpfully adds a css class upon fail.
Some time ago I spend a few hours on it and since then I have been using some custom js magic to accomplish this.
In fact is quite simple and in the way that ASP.NET validation works. The basic idea is add a css class to attach a javascript event on each control you want quick visual feedback.
<script type="text/javascript" language="javascript">
/* Color ASP NET validation */
function validateColor(obj) {
var valid = obj.Validators;
var isValid = true;
for (i in valid)
if (!valid[i].isvalid)
isValid = false;
if (!isValid)
$(obj).addClass('novalid', 1000);
else
$(obj).removeClass('novalid', 1000);
}
$(document).ready(function() {
$(".validateColor").change(function() {validateColor(this);});
});
</script>
For instance, that will be the code to add on an ASP.Net textbox control. Yes, you can put as many as you want and it will only imply add a CssClass value.
<asp:TextBox ID="txtBxEmail" runat="server" CssClass="validateColor" />
What it does is trigger ASP.Net client side validation when there is a change on working control and apply a css class if it's not valid. So to customize visualization you can rely on css.
.novalid {
border: 2px solid #D00000;
}
It's not perfect but almost :) and at least your code won't suffer from extra stuff. And
the best, works with all kind of Asp.Net validators, event custom ones.
I haven't seen something like this googling so I wan't to share my trick with you. Hope it helps.
extra stuff on server side:
After some time using this I also add this ".novalid" css class from code behind when need some particular validation on things that perhaps could be only checked on server side this way:
Page.Validate();
if (!requiredFecha.IsValid || !CustomValidateFecha.IsValid)
txtFecha.CssClass = "validateColor novalid";
else
txtFecha.CssClass = "validateColor";
Here is my solution.
Advantages over other solutions:
Integrates seamlessly with ASP.NET - NO changes required to code. Just call the method on page load in a master page.
Automatically changes the CSS class when the text box or control changes
Disadvantages:
Uses some internal features of ASP.NET JavaScript code
Tested only on ASP.NET 4.0
HOW TO USE:
Requires JQuery
Call the "Validation_Load" function when the page loads
Declare a "control_validation_error" CSS class
function Validation_Load() {
if (typeof (Page_Validators) != "object") {
return;
}
for (var i = 0; i < Page_Validators.length; i++) {
var val = Page_Validators[i];
var control = $("#" + val.controltovalidate);
if (control.length > 0) {
var tagName = control[0].tagName;
if (tagName != "INPUT" && tagName != "TEXTAREA" && tagName != "SELECT") {
// Validate sub controls
}
else {
// Validate the control
control.change(function () {
var validators = this.Validators;
if (typeof (validators) == "object") {
var isvalid = true;
for (var k = 0; k < validators.length; k++) {
var val = validators[k];
if (val.isvalid != true) {
isvalid = false;
break;
}
}
if (isvalid == true) {
// Clear the error
$(this).removeClass("control_validation_error");
}
else {
// Show the error
$(this).addClass("control_validation_error");
}
}
});
}
}
}
}
Alternatively, just iterate through the page controls as follows: (needs a using System.Collections.Generic reference)
const string CSSCLASS = " error";
protected static Control FindControlIterative(Control root, string id)
{
Control ctl = root;
LinkedList<Control> ctls = new LinkedList<Control>();
while ( ctl != null )
{
if ( ctl.ID == id ) return ctl;
foreach ( Control child in ctl.Controls )
{
if ( child.ID == id ) return child;
if ( child.HasControls() ) ctls.AddLast(child);
}
ctl = ctls.First.Value;
ctls.Remove(ctl);
}
return null;
}
protected void Page_PreRender(object sender, EventArgs e)
{
//Add css classes to invalid items
if ( Page.IsPostBack && !Page.IsValid )
{
foreach ( BaseValidator item in Page.Validators )
{
var ctrltoVal = (WebControl)FindControlIterative(Page.Form, item.ControlToValidate);
if ( !item.IsValid ) ctrltoVal.CssClass += " N";
else ctrltoVal.CssClass.Replace(" N", "");
}
}
}
Should work for most cases, and means you dont have to update it when you add validators. Ive added this code into a cstom Pageclass so it runs site wide on any page I have added validators to.