As you might know, JQuery and
UpdatePanel
s are not friends. But some times we have to use JQuery.ajax() to design a small request(this could increase the permanence - smaller request means less bits to be transferred, and also a shorter waiting time between request and response.) In the same time we might need to use an
UpdatePanel
to hold some complex controls that change their appearance between round-trips.
as you might know, an
UpdatePanel
is rendered as a block (a div or a span depending on the RenderMode Property) that redraws itself every time its registered for update.
first we add the page markups.
<asp:Button ID="cmdBind" runat="server" Text="Bind Some Data" />
<table width="100%">
<tr>
<td style="width: 50%">
<asp:Label ID="lblLoading1" runat="server" Style="display: none;">Loading ...</asp:Label>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Repeater ID="SomeDataRepeater" runat="server">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<%#Eval("Data")%></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="cmdBind" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
</td>
<td style="width: 50%">
<asp:Label ID="lblLoading2" runat="server" Style="display: none;">Loading ...</asp:Label>
<asp:UpdatePanel ID="OtherDataPanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Repeater ID="SomeOtherDataRepeater" runat="server">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<%#Eval("Data")%></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
</td>
</tr>
</table>
On Page.Load handler we should add the code
cmdBind.OnClientClick = String.Format("javascript:$('#{0}').show();", lblLoading1.ClientID)
to show the text "Loading ..." when we click the button cmdBind.
Then on the handler we register to call the function <cond>BindSomeOtherDataRepeater() that will request the server again.
Private Sub cmdBind_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdBind.Click
BindSomeDataRepeater()
ScriptManager.RegisterStartupScript(Me, Me.GetType, "BindSomeOtherDataRepeater", "BindSomeOtherDataRepeater();", True)
End Sub
the data to send to the server should contain __EVENTTARGET and __EVENTARGUMENT to cause a regular post-back event.
function BindSomeOtherDataRepeater(){
$('#<%= lblLoading1.ClientID %>').hide();
$('#<%= lblLoading2.ClientID %>').show();
$.ajax({
type: "POST",
url: "<%= ResolveClientUrl(Me.Request.CurrentExecutionFilePath) %>",
dataType: 'text',
data: GetData(),
success: function (msg) {
$("#<%= lblLoading2.ClientID %>").hide();
UpdateOtherDataPanel(msg);
}
});
}
function GetData() {
return {
__EVENTTARGET : '<%= Me.UniqueID %>',
__EVENTARGUMENT : 'other'
};
}
function UpdateOtherDataPanel(msg) {
var div = toElement(msg);
$('#<%= OtherDataPanel.ClientID %>').html($(div).html());
}
function toElement(html) {
var div = document.createElement('div');
div.innerHTML = html;
var el = div.childNodes[0];
div.removeChild(el);
return el;
}
we can catch this event by implementing the interface
IPostBackEventHandler
.
Public Sub RaisePostBackEvent1(ByVal eventArgument As String) Implements System.Web.UI.IPostBackEventHandler.RaisePostBackEvent
If eventArgument = "other" Then
BindSomeOtherDataRepeater()
UpdateOtherDataPanel()
End If
End Sub
lastly we send the resulting html of the
UpdatePanel
in the response
Public Sub UpdateOtherDataPanel()
Dim div As New HtmlGenericControl("div")
div.Controls.Add(SomeOtherDataRepeater)
Response.Clear()
Response.ContentType = "text"
Dim twriter As New IO.StringWriter
Dim writer As New Html32TextWriter(twriter)
div.RenderControl(writer)
Response.Write(twriter.ToString())
Response.End()
End Sub