最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to retain script block on a partial postback? - Stack Overflow

programmeradmin0浏览0评论

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 pared 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.

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 pared 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.

Share Improve this question edited Nov 29, 2010 at 15:36 Koekiebox 5,97314 gold badges55 silver badges88 bronze badges asked Nov 20, 2010 at 5:42 BeemerGuyBeemerGuy 8,2792 gold badges38 silver badges47 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 8 +50

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.

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.

发布评论

评论列表(0)

  1. 暂无评论