11

Has anyone else seen something like this?

1) Create a component that includes a javascript block (OK, the code is overkill, but pretend it's actually doing something):

<apex:component layout="block">
    <script>
        (function () {
            "use strict";
            console.debug('Hello, World!');
        })();
    </script>
</apex:component>

2) Add the component to a VF page. Load the page, and you see the debug message in your console. If you examine the source, the script is included in the page exactly as written.

<apex:page>
    <c:MyComponent/>
</apex:page>

3) Now adjust your VF page so that the component is re-rendered at some point after the initial page load. The code no longer runs -- there's no message in the console, and breakpoints added to the block do nothing. Furthermore, if you examine the source, you see that SFDC has added CDATA blocks around the code (although they theoretically shouldn't do anything).

<div id="scary:SF:id:block">
    <script>
    //<![CDATA[
        (function () {
            "use strict";
            console.debug('Hello, World!');
        })();
     //]]>
    </script>
</div>

WHAT GIVES? Has anyone else seen this? Know any workarounds? How can I get my code blocks to run after a rerender? I've tested, and this behavior is consistent across FF and Chrome.

2
  • Are you sure it is actually reRendering the component? There was another question about apex:component not reRendering recently. – Peter Knolle Mar 8 '13 at 23:52
  • Quite positive -- the component looks totally different after rerendering. I can also see the <script> in the page source, and it's not there before the rerender -- it's just not running! – Benj Mar 11 '13 at 0:45
2

Most browsers specifically prevent the execution of javascript which is inserted into the page a later time as a means to protect the user from potential malicious code.

If you want to fire the code your best bet is to call the function using on onComplete() handler for the action function or command button being used.

You can also use the eval() javascript function to run dynamically created code which is available for precisely this purpose.

8
  • That makes sense, but it's weird that this only happens with <script>s in <apex:component>s. When the <script> is rerendered directly in an <apex:page>, it executes fine. – Benj Mar 8 '13 at 14:18
  • And even if I plan to use onComplete, I can't even define the code to run inside the component, because it will never run. – Benj Mar 8 '13 at 14:20
  • What do you mean you can't define the code? Isn't it generated in the component? If you shove it all into a javascript string you can call it with eval() or just jQuery to grab it and pass it to eval(). – Matt Lacey Mar 8 '13 at 22:19
  • I mean I can't include something like function doThis () { whatever(); } within the component and then call it with onComplete following rerender, because the script doesn't run and therefore the function doesn't exist. Would like to avoid using eval if at all possible, but that may be a work-around option. – Benj Mar 11 '13 at 0:40
  • 1
    I'm no longer having this issue, having made no relevant changes. I'm guessing there was a weird bug in the system, and will propose to those this question as too specific. – Benj Mar 19 '13 at 2:06
1

I haven't had a problem with executing JavaScript in reRendered sections or reRendered components. I just created a simple VF page with a simple controller that reRenders an apex:component with your Hello World, after that component wasn't originally rendered and it did it without any issues. The only catch is that the actual component specified in the reRender is an apex:outputPanel wrapper, which needs to be used since the component isn't originally on the page.

Here is the code.

Visualforce Page

<apex:page controller="MyCompPageController">

<apex:form >
    <apex:commandButton value="ReRender My Component" 
          action="{!handleReRenderClick}" reRender="myComponentWrapper"/>
</apex:form>
<apex:outputPanel id="myComponentWrapper">
    <!-- renderIt is originally false, so component won't show, then 
         on the commandButton action it will be set to true -->
    <c:mycomponent id="myComponent" rendered="{!renderIt}" />
</apex:outputPanel>

Controller

public class MyCompPageController {
    public Boolean renderIt { get; set; }

    public PageReference handleReRenderClick() {
        renderIt = true;
        return null;
    }
}

Component

<apex:component layout="block">
    <script>
        (function () {
            "use strict";
            console.debug('Hello, World!');
        })();
    </script>
</apex:component>

You have to look closely at the Chrome Developer Console output as it doesn't repeat the line but just increments a counter next to it. Chrome Developer Console Incrementing Counter

I have had issues where JavaScript mixed with Visualforce results in syntactically incorrect JavaScript resulting in the JavaScript not executing, sometimes with nothing reported in the console. In those situations it was my code that was bad and not a browser or VF issue. I usually look for any Visualforce code (e.g., variable not set, VF property not evaluating to valid JavaScript type, etc.) in the JavaScript as being the source of the problem. In those situations, where the debugger seems to not work anymore, I usually pare down the code to something simple and add back chunks until it works.

Also, not sure if you are using jQuery or not, but if you have some sort of event handler that uses something like a class selector in your page level JavaScript that executes when the page originally loads and you reRender something with that class it will not be hooked into that event handler, since the code to do that just executes that one time on page load.

5
  • Weird. Works for you, doesn't work for me; I'll have to take a closer look and see if there are some obscure typos or something. Thanks! – Benj Mar 11 '13 at 16:58
  • what happens if you hide the component at first (rendered evaluated to false) and then use the commandButton to reveal it? – Benj Mar 11 '13 at 16:59
  • 1
    @Benj - That works for me as well, but I have to reRender an outputPanel "wrapper" and not the actual component, because the component isn't on the page originally. I updated my answer with that code. – Peter Knolle Mar 12 '13 at 0:41
  • @Benj - You may want to take a look at the Chrome Developer Console Network tab as it will allow you to inspect the actual response from the server. You'll see your rerendered section and some other information SF sends along for processing. – Peter Knolle Mar 13 '13 at 10:17
  • I've been looking at it all along, and I see exactly what I described. The script is there, but doesn't seem to run... – Benj Mar 13 '13 at 17:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.