How to retain script block on a partial postback?
Asked Answered
B

2

8

This is a problem I'm facing in a webapp I'm currently working on.
So instead of cluttering the question with unrelated code, I recreated the problem in an isolated, simplified webapp that only demonstrates this issue.
Hopefully this helps in finding a solution.

I have a web user control with just this as its content:

<% if (ShowAlertScript)
   { %>
       <script type="text/javascript">
           function AlertMe() 
           {
               alert('Hello World!');
           }
       </script>
<% } %>
<input type="button" onclick="AlertMe()" value="Say Hello" />

And its codebehind has nothing more than the boolean definition of ShowAlertScript.
This represents a control I have in the big webapp that has two modes: input mode, and display mode. When in input mode, it has a large javascript block that is only useful then; it does some cool stuff to help the user input the info.

The way this control is laid out in the big picture is as follows:

<asp:ScriptManager runat="server" />
<asp:UpdatePanel runat="server">
  <ContentTemplate>
    <asp:MultiView ActiveViewIndex="0" runat="server" ID="mvw">
      <asp:View runat="server">
        <asp:Button runat="server" ID="btnSwitch" 
            OnClick="btnSwitch_Click" Text="Switch" />
      </asp:View>
      <asp:View runat="server">
        <uc:MyInputControl runat="server" ID="micInput" ShowAlertScript="true" />
      </asp:View>
    </asp:MultiView>
  </ContentTemplate>
</asp:UpdatePanel>

When you click btnSwitch, it simply switches to the second view with the user control. Notice how I have the ShowAlertScript already initialized to true.
The potential output is that since I'm "showing the alert script" within the user control, the AlertMe() function will execute when you click the input-button element, because it's written out according to the inline if statement.

If you run this code I gave you so far as is, it will not work.
The browser will say it can't see the AlertMe() function; it's undefined as far as it knows. But if you take out the UpdatePanel (or disable the ScriptManager's partial rendering), it will work just fine on a full postback when you click btnSwitch.

I want it to work on a partial postback, because this whole thing is a small piece compared to the rest of the page, and I don't want to do a full postback every time they switch views.
Apparently, the ScriptManager doesn't even bother re-rendering the ascx file for possible changes.
Either the ScriptManager is not smart enough, or there is an option I'm missing to let it render the <script> so I can invoke its methods on the client side.

A potential answer someone might suggest is "why don't you take out the javascript, put it in its own .js file, and have the page reference it so it's available to the control?"
That won't really work with me, because the script block does some initialization and modification that pertain to that single control instance, not to all others on the page.

In turn, you might also be concerned that if I have more than one instance of the control, I end up with copies of the same script. Not really; there will only be ONE input mode of this control in a page at any given time, it's just that I have those two modes in two separate views and I let the user switch between them.

Thanks for just reading this far =)
Appreciate any help and input.

Botelho answered 20/11, 2010 at 5:42 Comment(0)
A
8

For your script block to properly support partial page rendering, you have to register it during the PreRender phase of your user control, using the ScriptManager.RegisterClientScriptBlock() method:

protected void Page_PreRender(object sender, EventArgs e)
{
    if (ShowAlertScript) {
        ScriptManager.RegisterClientScriptBlock(this,
            typeof(YourUserControl), "AlertScript",
            @"function AlertMe() 
              {
                  alert('Hello World!');
              }",
            true);
    }
}

(The above assumes you have the AutoEventWireup attribute set to true in the @ Control directive of your ascx file.)

Also, since the script is registered from a user control but your ScriptManager resides on the page itself, you'll probably have to add an <asp:ScriptManagerProxy> element to your control markup for the above to work.

Alternation answered 22/11, 2010 at 19:26 Comment(0)
P
1

UpdatePanels actually have their content changed by the AJAX framework setting innerHTML on the div corresponding to the UpdatePanel control.

Script elements are not executed when innerHTML is set.

Therefore, there is no way to have inline (i.e. declarative) JS executed during a partial postback.

Phonic answered 22/11, 2010 at 19:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.