UpdatePanel startup script not executing - asp.net

I'm writing an ASP.NET webpart for use in a SharePoint site and trying to use an UpdatePanel to render query results. I want to use a JQuery plugin to modify the table returned from the asynchronous postback, but I'm having trouble getting the startup script to execute on the asynchronous udpate.
I found this post which indicates that the UpdatePanel won't do an eval() on startup scripts; instead, you must register the startup script block with the ScriptManager. It all makes sense until it doesn't work. The MSDN reference documentation seems to concur with the approach taken there.
My control is too long to post completely, but here's a trimmed-down representation that I think covers anything relevant. Forgive me if there are missing controls in the paste below - I had to remove some parts, and there may be some dangling tentacles, so to speak. The below is the code for the webpart, which is not unlike the SmartPart which loads a user control (.ascx).
As you can see, I am using the ScriptManager.RegisterStartupScript method. I've tried both overloads; once for the Page, and once for the ListView (renamed as 'AspListView') which is in the update panel. In neither case does the startup script execute on the asynchronous update, and I'm at a loss for why.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
namespace MyNamespace
{
using AspListView = System.Web.UI.WebControls.ListView;
[Guid("601b3bdb-ed2a-4ec8-8a40-c37de8ab048d")]
public class ListSearch : StaticTemplateWebPart
{
private AspListView resultsList;
public ListSearch()
{
}
protected override void CreateChildControls()
{
base.CreateChildControls();
ScriptLink.Register(Page, "jquery-1.3.2.js", false);
ScriptLink.Register(Page, "jquery-ui-1.7.2.custom.min.js", false);
ScriptLink.Register(Page, "jquery.timepickr.js", false);
ScriptLink.Register(Page, "jquery.quicksearch.js", false);
string scriptBlock =
#"
if ($('table#discrepancy-results').length)
{
$('table#discrepancy-results tr').quicksearch({
position: 'before',
attached: 'table.results',
stripeRowClass: ['odd', 'even'],
labelText: 'Keyword Search'
});
}";
ScriptManager.RegisterStartupScript(Page, typeof(Page), UniqueID, scriptBlock, true);
/* adding other controls, getting references, databinding, etc. */
}
void searchButt_Click(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
var beginDT = DateTime.Parse((beginDateText.Text ?? "") + " " + (beginTimeText.Text ?? ""));
var endDT = DateTime.Parse((endDateText.Text ?? "") + " " + (endTimeText.Text ?? ""));
var dataList = SPContext.Current.Web.Lists["MyDataList"].Items;
var results = SearchListItems(dataList, beginDT, endDT, keywordText.Text ?? "");
if (results.Count > 0)
{
resultsList.DataSource = results;
resultsList.DataBind();
}
}
}
}
}
And the user control that gets loaded:
<%# Control Language="C#" ClassName="ListSearchControl" %>
<% if (false)
{ %>
<script src="../../LAYOUTS/jquery-1.3.2-vsdoc2.js" type="text/javascript"></script>
<% } %>
<script type="text/javascript">
$(function() {
$('id').trigger('click');
$('#<%= BeginTime.ClientID %>').timepickr({
handle: '#<%= BeginTimeTrigger.ClientID %>',
convention: 12,
trigger: 'nothing'
});
$('#<%= EndTime.ClientID %>').timepickr({
handle: '#<%= EndTimeTrigger.ClientID %>',
convention: 12,
trigger: 'nothing'
});
});
</script>
<asp:Panel ID="ControlPanel" runat="server">
<asp:Panel ID="Inputs" runat="server">
<asp:Panel CssClass="DateInputWrapper" runat="server">
<asp:Panel CssClass="BeginDateInput" runat="server">
<asp:Label Text="Begin Date: " runat="server" />
<asp:TextBox ID="BeginDate" Columns="14" runat="server"></asp:TextBox>
<asp:Image ID="BeginDateImg" ImageUrl="/_layouts/Images/calendar.gif" runat="server" />
<ajax:CalendarExtender ID="BeginDateExtender" TargetControlID="BeginDate" PopupButtonID="BeginDateImg"
Format="MMMM d, yyyy" runat="server">
</ajax:CalendarExtender>
<asp:Label Text="Begin Time: " runat="server" />
<asp:TextBox ID="BeginTime" Columns="6" Text="04:00 am" runat="server"></asp:TextBox>
<asp:Image ID="BeginTimeTrigger" runat="server" ImageUrl="/_layouts/1033/Images/clock.png" />
</asp:Panel>
<asp:Panel CssClass="EndDateInput" runat="server">
<asp:Label Text="End Date: " runat="server" />
<asp:TextBox ID="EndDate" Columns="14" runat="server"></asp:TextBox>
<asp:Image ID="EndDateImg" ImageUrl="/_layouts/Images/calendar.gif" runat="server" />
<ajax:CalendarExtender ID="EndDateExtender" TargetControlID="EndDate" PopupButtonID="EndDateImg"
Format="MMMM d, yyyy" runat="server">
</ajax:CalendarExtender>
<asp:Label Text="End Time: " runat="server" />
<asp:TextBox ID="EndTime" Columns="6" Text="03:59 am" runat="server"></asp:TextBox>
<asp:Image ID="EndTimeTrigger" runat="server" ImageUrl="/_layouts/1033/Images/clock.png" />
</asp:Panel>
</asp:Panel>
<asp:Panel CssClass="Submit" runat="server">
<asp:Button ID="SearchButton" Text="Search" runat="server" />
<asp:Label CssClass="SearchStatusText" runat="server" />
</asp:Panel>
</asp:Panel>
</asp:Panel>
<asp:Panel ID="ResultsPanel" runat="server">
<asp:ListView ID="ResultsList" runat="server">
<LayoutTemplate>
<table id="discrepancy-results">
<tr class="header-row">
<th>Scheduled Date/Time</th>
<th>Code</th>
<th>Description</th>
</tr>
<asp:PlaceHolder runat="server" ID="itemPlaceHolder" />
</table>
</LayoutTemplate>
<ItemTemplate>
<tr class="result-row">
<td><%# Eval("ScheduledDate") %></td>
<td><%# Eval("Code") %></td>
<td><%# Eval("Description") %></td>
</tr>
</ItemTemplate>
</asp:ListView>
</asp:Panel>
<asp:Panel ID="DetailsPanel" runat="server">
</asp:Panel>

I'd like to add that the updatepanel startupscripts wouldn't work for us unless you used the UpdatePanel's ID, and typeof(UpdatePanel). Using startupscripts elsewhere outside an updatepanel wasn't as fussy. We got this working like this:
ScriptManager.RegisterStartupScript(UpdatePanelId, typeof(UpdatePanel), "myScript",
/ *
* Register a startup script to run
* on the client after running this method on the server
* /
#" alert('Add your function to replace this.');", true);
The solution presented by Darin would work as well, but in our case the updatepanel has more functionality and would require additional logic to 'track' what was being done so the script wouldn't execute on every single update to the update panel, but only after a certain event. This way the script is only executed on this event.

Instead of using ScriptManager.RegisterStartupScript here's something else you might try. Register for the end_request event of the UpdatePanel and execute your jQuery script:
// This could also be done in jQuery's $(document).ready
function pageLoad() {
Sys.WebForms
.PageRequestManager
.getInstance()
.add_endRequest(endRequestHandler);
}
function endRequestHandler(sender, args) {
// Shouldn't the next test be:
// $('table#discrepancy-results').length > 0 ???
// and is it necessary at all? I suppose the quicksearch plugin
// won't apply on empty array
if ($('table#discrepancy-results').length) {
$('table#discrepancy-results tr').quicksearch({
position: 'before',
attached: 'table.results',
stripeRowClass: ['odd', 'even'],
labelText: 'Keyword Search'
});
}
}

ScriptManager.RegisterStartupScript takes a parameter key, which you are setting to the control's UniqueID. This key needs to be unique during page scripts execution. So, you should change this line:
ScriptManager.RegisterStartupScript(Page, typeof(Page), UniqueID, scriptBlock, true);
with
ScriptManager.RegisterStartupScript(Page, typeof(Page), Guid.NewGuid(), scriptBlock, true);
or some other way you like to generate unique keys.

after playing with it a bit, I got it to work. I think the problem was that I was just using quicksearch() incorrectly somehow. I tried later with a simple alert() and it worked fine. Thanks for the suggestions!

Related

Passing CommandArguement to LinkButton from variable

I have seen many resources on SO that say that I can use following syntax to pass value to CommandArguement of `LinkButton'
<%forearch(var comment in Comments){%>
<asp:LinkButton ID="del" CommandArguement='<%= comment.CommentId%>' onCommand="delete_click" Text="Delete"/>
<%}%>
But when I write this in my ascx file and click on the link the value passed to command argument is "<%=comment.CommentId%>" instead of commentId itself. Please guide what am I doing wrong?
Edit 1
based on answers and comments, I have moved to use repeater instead of foreach and plain code. Here is the code I have come up with
<asp:Repeater ID="commRepeater" SelectMethod="GetPageComments" runat="server">
<ItemTemplate>
<p>
<%#Eval("Comment") %>
<%if(Page.User.Identity.IsAuthenticated && Page.User.Identity.GetUserId() == Eval("UserId")){ %>
<span>
<asp:LinkButton Text="Edit" runat="server" ID="EditLink" CommandArgument='<%#Eval("CommentId")%>' OnClick="Update_Comment" />
<asp:LinkButton Text="Delete" runat="server" ID="DeleteLink" CommandArgument='<%#Eval("CommentId")%>' OnClientClick="if (!confirm('Are you sure you want delete?')) return false;" OnCommand="Delete_Comment" />
</span>
<%} %>
</p>
</ItemTemplate> </asp:Repeater>
you can see that I am trying to show the edit and delete links if user is logged in and his Id matches with user who commented but it tells me that I can on use Eval in databound controls. how would I hide/show edit/delete links conditionally within repeater
You could simply use codebehind, for example in Page_Load:
protected void Page_Load(Object sender, EventArgs e)
{
if(!IsPostBack)
{
del.CommandArgument = comment.CommentId;
}
}
Maybe a better approach would be to use the Comments-collection(which seems to be a list or array of a custom class) as DataSource of a Repeater(or other web-databound control). Then you can add the LinkButtons to the Itemtemplate.
You can then either use ItemCreated or ItemDataBound events of the repeater in codebehind or inline ASP.NET tags to bind the CommandArgument.
For example:
CommandArguement='<%# DataBinder.Eval( Container.DataItem, "CommentId" ) %>'
What you are doing currently is not recommended and is highly error prone. You can easily achieve this with ASP.NET Repeater control like this:-
<asp:Repeater ID="MyRepeater" runat="server">
<ItemTemplate>
<asp:LinkButton ID="del" CommandArguement='<%# Eval("CommentId") %>'
OnCommand="del_Command" Text="Delete" runat="server" />
</ItemTemplate>
</asp:Repeater>
In Page_Load simply bind it:-
if (!Page.IsPostBack)
{
MyRepeater.DataSource = CommentsRepository();
MyRepeater.DataBind();
}
Or Else if you are have ASP.NET 4.5 then use strongly type Data Bound controls like this:-
<asp:Repeater ID="MyRepeater" runat="server" ItemType="MyNamespace.Comment"
SelectMethod="MyRepeater_GetData">
<ItemTemplate>
<asp:LinkButton ID="del" CommandArguement='<%# Item.CommentId %>'
OnCommand="del_Command" Text="Delete" runat="server" />
</ItemTemplate>
</asp:Repeater>
And you method in code behind should be something like this(just for Demo):-
public IEnumerable<MyNamespace.Comment> MyRepeater_GetData()
{
return new List<Comment>
{
new Comment { CommentId =1, Name= "foo"},
new Comment { CommentId =2, Name= "bar"},
};
}

How to call sub onchange of a dropdownlist while using AJAX?

So, I know how to call a method onclick of a button using ajax, but I'd like to do the same when a user selects something new on a dropdownlist. I'll show code for what I've tried below:
<asp:UpdatePanel ID="pnlHelloWorld" runat="server">
<ContentTemplate>
<div style="height: auto; overflow: auto; max-height:750px; width:100%;">
<asp:DropDownList ID="mydropdownlist" runat="server" Enabled="true" OnChange="changeMyTable"></asp:DropDownList>
<asp:Table ID="mytable" runat="server"></asp:Table>
</div>
</ContentTemplate>
</asp:UpdatePanel>
In the page's aspx.vb:
Private Sub changeMyTable()
'Add rows to table
end sub
The problem is that "changeMyTable" is undefined when i change the dropdownlist.
How can I do this?
You are using the OnChange event to call the code behind method from javascript. To access the code behind method you need to convert that method to the WebMethod. For that below is something you can try (Just an example)
<asp:TextBox ID="txtName" runat="server"></asp:TextBox>
<asp:TextBox ID="txtLastName" runat="server"></asp:TextBox>
<asp:TextBox ID="txtMsg" runat="server"></asp:TextBox>
Javascript code -
<script type="text/javascript">
function greet(txtN, txtLastN, txtMsg){
var ctrlN = document.getElementById(txtN);
var ctrlLastN = document.getElementById(txtLastN);
var fullName = ctrlN.value + ' ' + ctrlLastN.value;
PageMethods.greetUser(fullName, greetSuccess, greetFailed, txtMsg);
}
function greetSuccess(res, txtMsg) {
var ctrlTxtMsg = document.getElementById(txtMsg);
ctrlTxtMsg.value = res;
}
function greetFailed(res, dst) {
alert(res.get_message());
}
</script>
Code behind method -
<System.Web.Services.WebMethod()> _
Public Shared Function greetUser(ByVal fullName As String) As String
Return "Welcome " & fullName & "!"
End Function
Now you can call your javascript function greet from wherever you want and it will trigger the code behind method greetUser. More on this is available here.

How to access user control page dropdownlist control id from main page's javascript function?

main page :
<%# Register TagPrefix="A" TagName="AA" Src="~/UserControls/ab.ascx" %>
<A:AA id="a1" runtat="server" />
<asp:Button ID="btn" Visible="true" runat="Server" OnClick="Btn_Click" OnClientClick="javascript:PreLoad();" />
<script type="text/javascript">
function PreLoad() {
var empty = '<%= (a1.FindControl("ddl")).ClientID %>';
// the above line giving error as 'ddl is inaccessible due to its protection level'
}
</script>
in Usercontrol page:
<%# ControlLanguage="C#" AutoEventWireup="true" CodeBehind="ab.ascx.cs" inherits="ab.ascx.designer.cs" %>
<asp:DropDownList ID="ddl" runat="server"> </asp:DropDownList>
in ab.ascx.designer.cs
protected global::System.Web.UI.WebControls.DropDownList ddl;
Someone please explain the clean and simple proper way to access the 'ddl' inside the 'PreLoad()'
javascript function?
Change your tag to:
<asp:DropDownList ID="ddl" runat="server" ClientIDMode="static"> </asp:DropDownList>
This means that the control is rendered using the exact ID that you specified.
Then change your javascript to use the exact id of the control and access it by:
document.getElementById("ddl");
Or with jQuery:
$("#ddl");
Ideally you should move this javascript code to an external file too.

Can a button validate more validation groups?

I have 3 types of validators:
It is part of "VG1" validation group
It is part of "VG2" validation group
It is not part of any validation groups
I have two buttons, B1 and B2.
I would like to validate B1.Click if and only if all validators of the first and third type successfully validated the controls associated to them.
I would like to validate B2.Click if and only if all validators of the second and third type successfully validated the controls associated to them.
Is this possible in ASP.NET? If so, can you tell me how can I do this or where could I read something which would enlighten me in this question?
EDIT:
function isValidButton1()
{
var VG1 = Page_ClientValidate("VG1");
var empty = Page_ClientValidate("");
return VG1 && empty;
}
This works well, however, if VG1 is invalid, then the messages will disappear, because of the validation of the empty group. Is there a solution to show all validation error messages? Thank you.
EDIT2:
function isValidSaveAsClosed()
{
Page_ClientValidate("");
Page_ClientValidate("VG1");
var groups = [];
groups[0] = undefined;
groups[1] = "VG1";
var valid = true;
for (var f in Page_Validators)
{
if (jQuery.inArray(Page_Validators[f].validationGroup, groups) >= 0)
{
ValidatorValidate(Page_Validators[f]);
valid = valid && Page_Validators[f].isvalid;
}
}
return valid;
}
The function above solves my problem.
<asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="return Validate()" />
<script type="text/javascript">
function Validate()
{
var isValid = false;
isValid = Page_ClientValidate('VG1');
if (isValid)
{
isValid = Page_ClientValidate('VG2');
}
return isValid;
}
</script>
try this....hope it will help
Yes a button can validate more then one validation groups.
Inside the button_click you can validate the groups as
Page.Validate("VG1");
Page.Validate("VG2");
if (Page.IsValid)
{
// Page is valid so proceed..!!
}
I am adding another answer since adding to my last existing answer would make the answer too big for anyone to read.
In this answer, I have expanded on my last answer so multiple validation groups are automatically hooked up both on client-side as well as server-side. This means you do not need to call Page_ClientValidate("group1,group2") in JavaScript onclick event of button, since it will occur automatically. Also, the server-side validation for multiple groups will happen automatically.
The markup and code-behind for this is given below. You can try the aspx code that I have provided and test it in a website project. To test if automatic server-side validation occurs, you must set EnableClientScript="false" for each of the three validators.
Explanation of approach for automatic validation of multiple groups
If you want to implement multiple validation groups, the following steps need to done in your aspx page. Make sure that in your markup you mention a comma-delimited list of validation groups for ValidationGroup property of button control if you need to validate multiple groups at a time.
you need to override the JavaScriptmethod IsValidationGroupMatch by adding JavaScript to end of your aspx page (The code for this override is given at end of markup code below and you can copy/paste it into your aspx page); this is a standard method provided by ASP.Net validation framework.
you need to hookup the button with multiple validation groups for client-side validation since this is NOT done automatically by ASP.Net; for this, you have to call the method HookupValidationForMultipleValidationGroups in code-behind in Page_Load event for each button that has multiple validation groups.(you can copy/paste this method given in second-code snippet into the code-behind of your aspx page)
you need to override the server-side method Validate to add functionality for multiple validation groups since this is missing in ASP.Net.(you can copy/paste this method given in second-code snippet into the code-behind of your aspx page)
Markup of aspx with multiple validation groups for a button
<%# Page Language="C#" AutoEventWireup="true" CodeFile="MultipleValidationGroupsByOneButton.aspx.cs" Inherits="MultipleValidationGroupsByOneButton" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
TextBox1 :
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="TextBox1 needs input" ControlToValidate="TextBox1" ForeColor="Red" ValidationGroup="group1"></asp:RequiredFieldValidator>
<br />
<br />
TextBox2 :
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ErrorMessage="TextBox2 needs input" ControlToValidate="TextBox2" ForeColor="Red" ValidationGroup="group2"></asp:RequiredFieldValidator>
<br />
<br />
TextBox3 :
<asp:TextBox ID="TextBox3" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" ErrorMessage="TextBox3 needs input" ControlToValidate="TextBox3" ForeColor="Red" ValidationGroup="group3"></asp:RequiredFieldValidator>
<br />
<br />
</div>
<asp:Button ID="btnMultipleValidationGroups" runat="server" Text="Validate group1 and group2" ValidationGroup="group1,group2" OnClick="btnMultipleValidationGroups_Click" />
<asp:Button ID="btnGroup1" runat="server" Text="Validate only group1" ValidationGroup="group1" OnClick="btnGroup1_Click" />
<asp:Button ID="btnGroup2" runat="server" Text="Validate only group2" ValidationGroup="group2" OnClick="btnGroup2_Click" />
<asp:Label ID="lblMessage" runat="server" ForeColor="Red" Font-Bold="true"></asp:Label>
<script type="text/javascript">
window["IsValidationGroupMatch"] = function (control, validationGroup) {
if ((typeof (validationGroup) == "undefined") || (validationGroup == null)) {
return true;
}
var controlGroup = "";
var isGroupContained = false;
if (typeof (control.validationGroup) == "string") {
controlGroup = control.validationGroup;
var controlGroupArray = [];
if (validationGroup.indexOf(",") > -1) {
controlGroupArray = validationGroup.split(",");// validationGroup.split(",");
}
for (var i = 0; i < controlGroupArray.length; i++) {
if (controlGroupArray[i].trim() == controlGroup.trim()) {
isGroupContained = true;
}
}
}
return (controlGroup == validationGroup || isGroupContained);
}
</script>
</form>
</body>
</html>
Code-behind of above aspx page
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class MultipleValidationGroupsByOneButton : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//always call this method in Page Load event for each button with multiple validation groups
HookupValidationForMultipleValidationGroups(btnMultipleValidationGroups);
}
//the method below will automatically hook up a button with multiple validation groups for client-side validation
private void HookupValidationForMultipleValidationGroups(IButtonControl button)
{
if (!Page.IsPostBack && button.ValidationGroup.Contains(","))
{
//hook up validation on client-side by emitting the appropriate javascript for onclick event of the button with multiple validation groups
PostBackOptions myPostBackOptions = new PostBackOptions((WebControl)button);
myPostBackOptions.ActionUrl = string.Empty;
myPostBackOptions.AutoPostBack = false;
myPostBackOptions.RequiresJavaScriptProtocol = true;
myPostBackOptions.PerformValidation = true;//THIS true value hooks up the client-side validation
myPostBackOptions.ClientSubmit = true;
myPostBackOptions.ValidationGroup = button.ValidationGroup;
// Add postback script so cleint-side validation is automatically hooked up for control with multiple validation groups
((WebControl)button).Attributes.Add("onclick", Page.ClientScript.GetPostBackEventReference(myPostBackOptions));
}
}
//Override default Validate method so server-side validation of buttons with multiple validation groups occurs automatically
public override void Validate(string validationGroup)
{
if (validationGroup.Contains(","))
{
string[] validationGroups = validationGroup.Split(",".ToCharArray());
foreach (string group in validationGroups)
{
Page.Validate(group);
}
}
base.Validate(validationGroup);
}
protected void btnMultipleValidationGroups_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
lblMessage.Text = "Button with multiple validation groups was clicked";
}
}
protected void btnGroup1_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
lblMessage.Text = "Button with Group1 validation group was clicked";
}
}
protected void btnGroup2_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
lblMessage.Text = "Button with Group2 validation group was clicked";
}
}
}
A simpler approach that does not involve writting any aditional code is to simply replicate the validators wherever they are needed, as shown in the sample below:
<div>
<asp:TextBox ID="txt1" runat="server" placeholder="field1" />
<asp:RequiredFieldValidator runat="server" ID="req1a" ControlToValidate="txt1" ValidationGroup="group1" Display="Dynamic" />
<asp:RequiredFieldValidator runat="server" ID="req1b" ControlToValidate="txt1" Display="Dynamic" />
</div>
<div>
<asp:TextBox ID="txt2" runat="server" placeholder="field2" />
<asp:RequiredFieldValidator runat="server" ID="req2" ControlToValidate="txt2" />
</div>
<!-- Validate validators with empty ValidationGroup -->
<asp:Button runat="server" ID="btn1" Text="Validate All" />
<!-- Validate group1 validators -->
<asp:Button runat="server" ID="btb2" Text="Validate Group 1" ValidationGroup="group1"/>
First button will validate both textboxes, even though they are in diferent groups, while the second one will only validate the first textbox.
You can use Page_ClientValidate(validationgroup) function to validate a validation grouop.
like
function Validate(vgroup) {
return Page_ClientValidate(vgroup);
}
You can try
<asp:Button ID="B1" runat="server" Text="Button"
OnClientClick="return Validate('VG1') && Validate() " />
<asp:Button ID="B2" runat="server" Text="Button"
OnClientClick="return Validate('VG2') && Validate() " />
This is an old post but I had the same issue recently and the way I solved it is as explained below.
You can copy the code given in this post into your ASP.Net website project and test it for yourself. The first button i.e. the one on left is validating three validation groups at same time unlike the other two buttons.
Just include the JavaScript given at end of aspx page in code below, in which I have overridden the validation function IsValidationGroupMatch so multiple groups can be validated. Then, if you want to validate multiple groups on client-side, you must call the function Page_ClientValidate("group1,group2,group6,group5") to which you simply pass a comma-delimited list of validation groups.
(NOTE: But remember that by using this approach you can validate multiple validation groups on client-side only. This does NOT automatically also validate multiple groups on server-side. You must call the API function of Page_ClientValidate on client-side since multiple groups validation will not get automatically hooked up by ASP.Net framework.)
Sample aspx page code that allows validating multiple groups at same time on client-side
<%# Page Language="C#" AutoEventWireup="true" CodeFile="MultipleValidationGroupsByOneButton.aspx.cs" Inherits="MultipleValidationGroupsByOneButton" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
TextBox1 :
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="TextBox1 needs input" ControlToValidate="TextBox1" ForeColor="Red" ValidationGroup="group1"></asp:RequiredFieldValidator>
<br />
<br />
TextBox2 :
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ErrorMessage="TextBox2 needs input" ControlToValidate="TextBox2" ForeColor="Red" ValidationGroup="group2"></asp:RequiredFieldValidator>
<br />
<br />
TextBox3 :
<asp:TextBox ID="TextBox3" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" ErrorMessage="TextBox3 needs input" ControlToValidate="TextBox3" ForeColor="Red" ValidationGroup="group3"></asp:RequiredFieldValidator>
<br />
<br />
</div>
<asp:Button ID="btnMultipleValidationGroups" runat="server" Text="Validate group1 and group2" onclientclick="if(!Page_ClientValidate('group1,group2,group3')) { return false;}" />
<asp:Button ID="btnGroup1" runat="server" Text="Validate only group1" ValidationGroup="group1" />
<asp:Button ID="btnGroup2" runat="server" Text="Validate only group2" ValidationGroup="group2" />
<script type="text/javascript">
window["IsValidationGroupMatch"] = function (control, validationGroup) {
if ((typeof (validationGroup) == "undefined") || (validationGroup == null)) {
return true;
}
var controlGroup = "";
var isGroupContained = false;
if (typeof (control.validationGroup) == "string") {
controlGroup = control.validationGroup;
var controlGroupArray = [];
if (validationGroup.indexOf(",") > -1) {
controlGroupArray = validationGroup.split(",");
}
for (var i = 0; i < controlGroupArray.length; i++) {
if (controlGroupArray[i].trim() == controlGroup.trim()) {
isGroupContained = true;
}
}
}
return (controlGroup == validationGroup || isGroupContained);
}
</script>
</form>
</body>
</html>

why ajax loader image always shown using jquery and asp.net

with asp.net code below my ajax_loader image doesn't work well and always shown ..
<asp:ScriptManager ID="MainScriptManager" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Label runat="server" ID="lblname">
Name</asp:Label><br />
<asp:TextBox runat="server" ID="txbname"></asp:TextBox><br />
<asp:Label ID="lblemail" runat="server">
Email</asp:Label><br />
<asp:TextBox runat="server" ID="txbemail" /><br />
<asp:Label runat="server" ID="lblsugg">
Suggestion</asp:Label><br />
<asp:TextBox runat="server" Rows="3" Columns="20" ID="txbsugg" TextMode="MultiLine"></asp:TextBox>
<asp:Button runat="server" ID="btnsubmit" OnClick="btnsubmit_onclick" Text="submit" />
<asp:Label runat="server" ID="lblresultmsg"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
<div id="loading">
<p>
<img src="Images/ajax-loader.gif" />
Please Wait</p>
</div>
and jquery code
$("#loading").ajaxStart(function() {
$(this).show();
}).ajaxStop(function() {
$(this).hide();
});
any suggestions !?
ajaxStart and ajaxStop works only for ajax request sent by jQuery, if you use other libraries or UpdatePanel, it won't help you.
jQuery only.
Whenever an Ajax request is about to be sent {With jQuery-gdoron}, jQuery checks whether there are any other outstanding Ajax requests. If none are in progress, jQuery triggers the ajaxStart event. Any and all handlers that have been registered with the .ajaxStart() method are executed at this time.
Example of jQuery ajax request that will fire the ajaxStart and ajaxStop:
$.ajax({
url: 'foo',
...
...
});
You could create a generic way to handle this by adding the following code to a common js include. Here's a quick and dirty example:
Note: Be sure you initialize it by calling SetupGlobalAjaxHandlers on your page load.
function SetupGlobalAjaxHandlers()
{
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
}
function InitializeRequest(sender, args)
{
if(typeof(OnPageInitRequest) != "undefined")
OnPageInitRequest();
}
function EndRequest(sender, args)
{
if(typeof(OnPageEndRequest) != "undefined")
OnPageEndRequest();
}
Then, in any page that includes the js file, you could optionally implement the OnPageInitiRequest() and OnPageEndRequest() methods. There, you could show/hide your loading indicator.
I do recommend, though, that you use an UpdateProgress control as you get the show/hide logic for free.
This technique opens up some possibilities for you, say, if you wanted to disable controls while a partial postback is occurring.

Resources