1

I have some buttons on my visualforce page which onclick, run a javascript function.

Sometimes however, the javascript function will need to run without the user actually clicking on the button. I need to call the javascript function from an apex method. How can I achieve this?

6
  • As written and without knowing more - you can't. Controllers cannot execute javascript on the vf page directly - however they can run the code in the controller that the javascript does (if thats what is happening)
    – Eric
    Nov 20, 2015 at 20:18
  • do you mean when you click on button first apex method called and after that javascript?
    – Ratan Paul
    Nov 20, 2015 at 20:19
  • I just need a way to to activate my javascript when one of my apex method variables becomes a certain number. ex) if (variable == 10) {activate javascript function} @Eric Nov 20, 2015 at 20:21
  • @Ratan see my most recent comment. Nov 20, 2015 at 20:22
  • 1
    How is your variable value being changed? You might be able to accomplish this with the oncomplete event of your apex tag, but knowing when the variable has become a value will require using a re-render to update the page's DOM, then a query selector to find the updated value. There is no direct way for Apex (server side) to invoke javascript (client side) and pass it a value.
    – dsharrison
    Nov 20, 2015 at 20:39

1 Answer 1

5

You can reRender scripts that should be run when conditions are met. I wrote up an arbitrary example where you have (approximately) a 50% chance of getting a popup dialog, and 50% chance of just plain text. Every five seconds, the server is called again, and you may get a dialog popup. This requires no user interaction.

public class showAlertRandom {
    public boolean showAlert { get; set; }
    public Decimal numberValue { get; set; }
    public showAlertRandom() {
        doRandomAlert();
    }
    public void doRandomAlert() {
        numberValue = Math.random();
        showAlert = numberValue < 0.5;
    }
}

<apex:page controller="showAlertRandom" showHeader="true">
    <apex:form id="form">
        <apex:outputText rendered="{!showAlert}" id="alert">
            <script>
            alert('Hello World');
            </script>
        </apex:outputText>
        <apex:outputText rendered="{!not showAlert}" id="noAlert">
            No alert this time, sorry. Random value was: {!numberValue}.
        </apex:outputText>
        <apex:actionPoller interval="5" action="{!doRandomAlert}" reRender="form" />
    </apex:form>
</apex:page>

How it works:

Though Apex Code can't call JavaScript directly, it can set a variable to render a script block that can run arbitrary code. On each render, when the variable is true, an alert is produced. I wouldn't try doing this inside a closure or the middle of a script block, as you'll probably get very unpredictable results. You could dispatch a custom event or call some global function, if you prefer. You can use this technique anywhere reRender is supported, such as on a commandLink, commandButton, and actionFunction.

5
  • Great answer @sfdcfox. I have used this in the past. I always feel guilty using this though as it seems like an odd design pattern to have a self-executing script block get called by the DOM when salesforce does a rerender rather than using a callback (or oncomplete) pattern, but I haven't come up with something better. TL;DR: This seems a bit dirty but it is quick and gets the job done.
    – dsharrison
    Nov 20, 2015 at 21:12
  • Interesting... I have never heard of actionPoller before. So this works because the javascript is contained within an apex block? Nov 20, 2015 at 21:14
  • It's an interesting approach. It's too bad that the minimum interval allowed on the actionPoller is 5 seconds. Still, it may be my only option. Thanks a lot! Nov 20, 2015 at 21:23
  • @AlexBrigham I don't think you need the actionPoller; you need any action. This could be a commandButton, commandLink, etc.
    – dsharrison
    Nov 20, 2015 at 21:24
  • @AlexBrigham You said, for example, you have a variable incremented by 1 on each button press, with each 10th call doing something. You can do that by reRendering the block with something like rendered="{!someVarabiable/10==0}".
    – sfdcfox
    Nov 20, 2015 at 21:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .