asp.net usercontrol won't fire javascript insi

2019-06-17 09:53发布

I've seen similar issues to this and answers but none seem to fix the issue.

I have a user control inside an update panel. Inside my user control I output javascript.

The javascript will not fire when triggered. If I move the javascript to the parent page outside of the usercontrol/updatepanels then it fires. This doesn't make sense to do this as I can't use this usercontrol on another page without either duplicating code...by either duplicating the entire javascript (different site) or adding references to a .js file in every page it's used on (same site). It's just less portable

I merely want to output the javascript with the control (inside the update panel).

The updatepanel is mentioned for accuracy of what I'm doing. It doesn't work even if I place the usercontrol outside of updatepanels.

Keeping it simple (This does not work for me):

USERCONTROL:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="_location.ascx.cs" Inherits="_location" %>
<script type="text/javascript">
    function test() {
        alert('Hello World!');
    }
</script>

<a href="javascript:void(0);" onclick="javascript:test();">
    Find For Me
</a>

PARENT:

<uc1:_location runat="server" ID="_location"  />

Debugging in chrome tells me "Uncaught ReferenceError: test is not defined"

If I add the javascript directly to the onclick as below, it works:

onclick="alert('Hello World!');"

And as stated above, moving the function to the parent page ALSO works.

It's as if the browser ignores the script output from the user control.

Any ideas?

5条回答
走好不送
2楼-- · 2019-06-17 10:26

When you have an UpdatePanel and that UpdatePanel updates it's content, it treats it's content as simple text/html (not code), it does not have any parser available to run the script and make it available for the page.

So this content,

<script type="text/javascript">
    function test() { alert('Hello World!'); }
</script>

<a href="javascript:void(0);" onclick="javascript:test();">
    Find For Me
</a>

after client side code of update panel runs and updates content of the page, the script part is not parsed - its simple text/html for the page.

This part however runs

<a href="javascript:void(0);" onclick="alert('Hello World!');">Find For Me</a>

because the parse of the onclick attribute is done when you click on it.

There are following workarounds available:

  1. Move your javascript into external file
  2. Move you script outside of the UpdatePanel
  3. Register the script in the code behind with RegisterClientScriptBlock or alternative functions.
查看更多
趁早两清
3楼-- · 2019-06-17 10:26

Thanks to Aristos for sending me down the right path... Though his solution works, it did not answer the question of outputting the javascript from inside the usercontrol but instead suggested moving it outside. This was not the desired outcome, as stated, as it's not kept inside the control for easier portability.

Here is my solution that accomplishes this: CS file:

String script = "<script type=\"text/javascript\">";
script += "function test() {";
    script += "alert('Hello World!');";
script += "</script>";

Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "locationScript", script);

One might use a stringbuilder if script is longer, but eitherway works.

This keeps the code entirely inside the usercontrol and it works from the onclick event of the a tag.

查看更多
做个烂人
4楼-- · 2019-06-17 10:27

In Addition to the solution that Adam Wood posted, I should say that you must use ScriptManager to register the script when using update panel, at least in .net 4.0 because otherwise it won´t work.

So you can put on the PageLoad event of the usercontrol:

string script = @" alert('this is a test');
alert('it worked')";
ScriptManager.RegisterStartupScript(Page,Page.GetType(),"scriptMelhoria",script,true);
查看更多
来,给爷笑一个
5楼-- · 2019-06-17 10:29

Preferred way of dealing with javscript code that is bound to DOM elements within UpdatePanel is to subscribe to endRequest event of PageRequestManager and execute your code here. For instance you want to set click event handlers here.

// that is standard way for asp.net to execute JS on page load
// pretty much the same as $(function(){ ...}) with jquery
function pageLoad() {
    // find PRM instance and subscribe to endRequest
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequest);
}

function endRequest() {
    // set all handlers to DOM elements that are within UpdatePanel
    $('<%= myButton.ClientID %>').on('click', test)
}

function test(e) {
   alert('Hi')
}

Alternative solution will be to use event delegation like so:

function pageLoad() {

    // delegate click event on .myButton inside .container
    // to the .container DOM element
    $('.container').on('click', '.myButton', test)

}

And have div with a class named container around your update panel. In this case your div.container is never removed from DOM so all event handlers on it will hold after partial postbacks.

Same code without jquery and using only asp.net ajax will look like this:

function pageLoad() {
   Sys.UI.DomEvent.addHandler($("myContainer"), "click", delegatedTest);
}

function delegatedTest(e) {
   // since asp.net ajax does not support event delegation
   // you need to check target of the event to be the right button 
   if (e.target.id == "myButton") test(e)
}

function test(e) {
   alert("HI")
}
查看更多
成全新的幸福
6楼-- · 2019-06-17 10:38

Try this;

You can find your script elements after udpdate panel callback and evaluate them.

Add a special attribute to your inline script tag to select elements after callback request.

<script type="text/javascript" data-tag='myscript'>
    function test() {
        alert('Hello World!');
    }
</script>

And add this script to your update panel container aspx file.

<script>

        if (Sys !== undefined) {
            var prm = Sys.WebForms.PageRequestManager.getInstance();
            prm.add_endRequest(endPostbackRequest);
        }

        function endPostbackRequest(sender, args) {
            $("script[data-tag='myscript']:not([data-run])").each(
                function () {
                    eval.apply(window, [$(this).text()]);
                    $(this).attr('data-run', '1');
                });
        }

</script>
查看更多
登录 后发表回答