I am trying to understand a bit about partial postbacks using updatepanels and while lots of things are stumping me, this one has me baffled.
I am using tabs inside of a UpdatePanel and becuase this is an data entry application, I am putting the content into user controls, so each tab has its own user control. In addition, I am adding custom javascript to each of the user controls to handle specific client side things for the stuff in that control.
In doing this though I have noticed that the javascript in the user control does not fire on partial page postbacks.
To simulate this I created a very simple app (using Master Pages with ScriptManager control on the master page) in VS2010.
The content panel of the default page has the following
<asp:UpdatePanel runat="server" UpdateMode="Conditional" ChildrenAsTriggers="true">
<ContentTemplate>
<asp:Button runat="server" ID="Button1" Text="Partial postback" />
<br />
<asp:Panel runat="server" ID="panel"></asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
Then I created a user control and simply added some plain text and a javascript alert
<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="UC1.ascx.vb" Inherits="TestWebApp_VB.UC1" %>
This is user control 1
<script> alert('control 1'); </script>
Then in the page load event of the Content page, I load the control into the panel.
Panel.Controls.Add(LoadControl("UC1.ascx"))
In addition on the click handler of the button I also load the control (or a different control when toggling, as described further in)
Button_Click
Panel.Controls.Clear()
Panel.Controls.Add(LoadControl("SomeControl.ascx"))
So when the page is first loaded the alert fires, however when you click the button and the page is partially posted back, the alert never fires.
I took this a step forward and created a second user control and had the button toggle loading the controls and also added a normal button outside the UpdatePanel. Any time I did the full postback the javascript in the loaded user control fires, but it never fires on the partial postbacks.
I then went one step forward and moved my javascript in the controls into a function so I could call the function from the PageRequestManager, or from document.ready.
So now my two controls contain this script (with the alert containing a different message for each control)
<script type="text/javascript">
function userLoad() {
alert("Identify control");
}
</script>
And thusly I added this to the end of my content panel
<script type="text/javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance().add_endRequest(userLoad);
</script>
Well now the javascript fires on every partial postback, however it fires the javascript for the control that last loaded by a full postback.
Example:
- Page intially loads UserControl1 - the alert for UserControl1 fires
(not shown here - the userLoad function is being called in jquery
document.ready)
- User clicks button - which should load UserControl2
- UserControl2 is loaded on the screen, but the alert for UserControl1
fires
A bit wordy, apologies for that, I found no easy way to explain this.
---Edit----
One of the things I have tried, working with Scotts suggestions. Keep the javascript for each control in a seperate file and put all of it into a function named something like function UC1Load() {} (maybe sticking a namespace around it, if I am feeling frisky), add a reference to the script file in the content page via a
<script src='UC1.js'>
then register startup script to call this function
ScriptManager.RegisterStartupScript(ctrl, ctrl.GetType(), "UserJS", "UC1Load()", True)
The biggest problem with this is that I am now having to download a bunch of script that wont ever be used, which is why I was putting the script in the user controls in the first place.