+ Start a Discussion
James@KronosLabJames@KronosLab 

How do you call an action from Javascript?

I'd like to call an action when a select is changed (using onchange).  However, a plain old submit doesn't call any action.  Looking at what a commandbutton generates, it's pretty hairy and specific, and I can't see a way to emulate it in user-written Javascript.  Any help here?

James
dchasmandchasman
great question - and there is a helper component designed to make this a snap.
Take a look at apex:actionSupport  - it allows you wire up any dom event
to an action - all without code (well a/out you writing any js - that's the visualforce team's job)!

FYI at some point in rhe future I do expect to provide a supported
js API equivalent for those rare occasions where the component
approach is not a good fit...

Message Edited by dchasman on 10-18-2007 05:30 PM

James@KronosLabJames@KronosLab
I assume you're talking about actionSupport, and if I could get it to work, I'd agree.  I've tried all of the below, and none of them make the form submit when the listbox changes value.

<apex:outputpanel>
<apex:selectOneListbox value="{!currentEmployee}" size="1">
<apex:actionsupport event="onchange" action="{!changeEmployee}"/>
<apex:selectItems value="{!employeeList}" />
</apex:selectOneListbox>
</apex:outputpanel>


<apex:outputpanel>
<apex:actionsupport event="onchange" action="{!changeEmployee}"/>
<apex:selectOneListbox value="{!currentEmployee}" size="1">
<apex:selectItems value="{!employeeList}" />
</apex:selectOneListbox>
</apex:outputpanel>

<apex:outputpanel>
<apex:actionsupport event="onchange" action="{!changeEmployee}">
<apex:selectOneListbox value="{!currentEmployee}" size="1">
<apex:selectItems value="{!employeeList}" />
</apex:selectOneListbox>
</apex:actionsupport>
</apex:outputpanel>

dchasmandchasman
Your first version is correct as far as apex:actionSupport and its relationship to the select list is concerned. apex:actionSupport is always a child of the component you are trying to enhance.

I expect that you do not have an <apex:form></apex:form> that contains your input/select elements. Without that you should be getting a javascript error complaining about this._form has no properties or some such nonsense.

In Winter '08 we have added save time validation for this kind of thing (although while investigating your question I found that this specific component does not check to insure it has been nested in a form - bug opened for that now).
James@KronosLabJames@KronosLab

Nope, it's inside a form.  Here's the complete snippet:

<apex:form><center>
<apex:outputpanel>
<apex:selectOneListbox value="{!currentEmployee}" size="1">
<apex:actionsupport event="onchange" action="{!changeEmployee}"/>
<apex:selectItems value="{!employeeList}" />
</apex:selectOneListbox>
</apex:outputpanel>
<apex:commandLink action="{!lastMonth}">&lt;-------</apex:commandLink>&nbsp;
&nbsp;
<apex:commandLink action="{!nextMonth}">-------&gt;</apex:commandLink>

</center>

James@KronosLabJames@KronosLab
Ok, I have it working (somewhat), must have been a browser caching issue.

However...  actionsupport have the same behavior as setting an action on a commandbutton.  The later causes the entire page to refresh, whereas actionsupport seems unable to do anything but a partial update, which makes my page break badly.  I've worked around it for the moment by putting a commandbutton next to the select to fire the action, but what would be really useful is a javascript function you can call to cause an action call with full refresh.

James
James@KronosLabJames@KronosLab
actionsupport *doesn't* have the same behavior, rather...
dchasmandchasman
actionSupport was specifically designed to provide partial page updates - first time somehas asked for a full page update version. commandButton supports the rerender attribute directly to provide the same partial page update capability that you are getting from actionSupport. Here is a working Summer '07 example:

<apex:page controller="Simple" showheader="false">
    <apex:form>
        <apex:outputText id="emp" value="The current employee: {!currentEmployee}"/><br/>
        <apex:outputpanel>
        <apex:selectOneListbox value="{!currentEmployee}" size="1">
            <apex:actionSupport event="onchange" action="{!changeEmployee}" rerender="emp"/>
            <apex:selectItems value="{!employeeList}" />
        </apex:selectOneListbox>
        </apex:outputpanel>
</apex:form>
</apex:page>

and the controller

public class Simple {

public SelectOption[] getEmployeeList() {
return new SelectOption[] { new SelectOption('A', 'A'), new SelectOption('B', 'B') };
}

public PageReference changeEmployee() {
return null;
}

public String getCurrentEmployee() {
return employee;
}

public void setCurrentEmployee(String employee) {
this.employee = employee;
}

public Simple() {
}

private String employee;
}

Can you please provide your entire page and controller? - I am just not following the thread of what you want to have happen versus your attempted workaround - thanks


Message Edited by dchasman on 10-19-2007 10:16 PM

QLDevQLDev
Apex 12.0 now provides a new tag <apex:actionFunction> and I've found it much more useful than the old actionSupport. You can use <apex:actionFunction> to hook apex action to any javascript enabled object.