+ Start a Discussion
LanceCresswellLanceCresswell 

VF Event Sequencing Problem

Hi folks,

I am having an event sequencing problem with my VF page.

Behind the onchange event of an inputField I am making an actionsupport call to the ApprovalRequired Method in my controller.  This method saves the approval result into the NeedsApproval property used by a inputHidden field.
           
<apex:pageBlock title="Selected {!$ObjectType.Product2.LabelPlural}" id="selected">                  
    <apex:inputHidden value="{!NeedsApproval}" id="needsapproval"/>               
    <apex:pageblockTable value="{!shoppingCart}" var="s" id="ProdTable">
        <apex:column headerValue="{!$ObjectType.OpportunityLineItem.Fields.Quantity.Label}">
            <apex:inputField value="{!s.Quantity}" style="width:70px" required="false">
                <apex:actionsupport event="onchange" action="{!ApprovalRequired}" rerender="selected">
                    <apex:param value="{!s.PriceBookEntryId}" assignTo="{!toCurrent}" name="toCurrent"/>                       
                </apex:actionsupport>                           
            </apex:inputField>
        </apex:column>
    </apex:pageblockTable>
</apex:pageBlock>

Further up the page the Save button calls an approvalReq js method

    <apex:commandButton action="{!onSubmitAll}" value="Save" onclick="if(!approvalReq()) return false;" style="width:60px"/>

This method checks the value found in the needsapproval element and displays a message stating that approval is required, do you wish to continue? If they do then the SubmitAll method is called.

The problem is if the user clicks the Save button immediately after entering a value in the quantity field the ApprovalRequired controller method has not fired or finished and so the approvalReq js method then picks up the previous value in the needsapproval element and not the latest.

The ApprovalRequired controller method logic is too difficult to right in js (as it uses custom settings etc) and so I'm not sure what the best approach is here.

Any help would be much appreciated.

Regards
Lance Cresswell
Best Answer chosen by LanceCresswell
Swati GSwati G
You will need to specify status is actionsupport. ActionStaus will show loading text to the user which wont allow user to click any thing on page.

Here is one page you can see.: http://testsiteatpsl-developer-edition.ap1.force.com/swatig16__TestVFPage

Code: 

  <apex:outputLabel value="User Input 1"></apex:outputLabel>
        <apex:inputText >
             <apex:actionSupport event="onchange" action="{!onChangeEvent}" status="status" reRender="dummy"/>
        </apex:inputText>
        <apex:outputLabel value="User Input 2"></apex:outputLabel>
        <apex:selectList size="1">
            <apex:selectOption itemValue="Test1" itemLabel="Test1"></apex:selectOption>
            <apex:selectOption itemValue="Test2" itemLabel="Test2"></apex:selectOption>
            <apex:actionSupport event="onchange" action="{!onChangeEvent}" status="status" reRender="dummy"/>
        </apex:selectList>
   
        <apex:commandButton action="{!onSubmitAll}" value="Save"  style="width:60px" />

<apex:actionStatus id="status">
        <apex:facet name="start">
            <div class="outerCls"></div>
            <div class="innerCls">
                Processing...
            </div>
        </apex:facet>
    </apex:actionStatus>                
    <style>
         .innerCls{
               left:50%;
               top:50%;
               position:fixed;
         }
         .outerCls{
             top: 0px;
            left: 0px;
            position: absolute;
            background-color: #CCC;
            opacity: 0.40;
            width: 100%;
            height: 100%;
        }
    </style>

All Answers

Swati GSwati G
Hi,
On change of inputField show actionstatus which will show wait message to the user, so that user will wait to complete the actionsupport process. You can show loading image in action status. You can set status on actionsupport.
LanceCresswellLanceCresswell
The actionstatus solution still doesn't stop the user clicking the Save button.

My latest thought was to update the approvalReq js function to call the setTimeOut function which delays the execution of the code correctly.  The delay works but I cannot get the result back to the buttons onclick event to determine whether the onSubmitAll action needs to take place.  The same code works fine when not run as part of the setTimeOut callback method.

I also cannot write the result to an element on the VF page and link it to a controller property because I cannot get the value to bind to the controller property before the onSubmitAll action fires.

The js
approvalReq function is shown below.

        function approvalReq(){
            //result = null;
            setTimeout(function(){
                var approvalRequired = document.getElementById('{!$Component.mainpage:mainform:selected:needsapproval}').value;
                var approvalServicesRequired = document.getElementById('{!$Component.mainpage:mainform:selectedservices:needsservicesapproval}').value;
                if(approvalRequired == 'Yes' || approvalServicesRequired == 'Yes')
                {
                    result = confirm('The discount needs approving. Saving this record will lock the Opportunity for editing while the approval is pending. Do you wish to continue?');           
                }
                else
                {
                    result = true;   
                }
                if (result == false){
                    document.getElementById('{!$Component.mainpage:mainform:selected:approvalDecision}').value = 'No';
                }
                if (result == true){
                    document.getElementById('{!$Component.mainpage:mainform:selected:approvalDecision}').value = 'Yes';
                }
            },
            2000);
            //if (result != null){
            //    return result;
            //}
        }


Anyone have any further ideas?

Regards
Lance Cresswell
Swati GSwati G
Hi,

Create actionStatus as given below and add it in commandbutton

<apex:actionStatus id="status">
        <apex:facet name="start">
            <div class="outerCls"></div>
            <div class="innerCls">
                Processing...
            </div>
        </apex:facet>
    </apex:actionStatus>

<style>
     .innerCls{
       left:50%;
       top:50%;
       position:fixed; 
     }
     .outerCls{
         top: 0px;
        left: 0px;
        position: absolute;
        background-color: #CCC;
        opacity: 0.40;
        width: 100%;
        height: 100%;
     }
</style>
LanceCresswellLanceCresswell
Thanks for taking time to reply.

I implemented the change as you described but it still doesn't stop the user actually clicking the Save button.  I need a fix that allows the ApprovalRequired controller method to execute behind the onchange event of the inputfield before the approvalReq js function behind the Save button fires.

Here's my implementation of your code (in case I've done it wrong!)

                <apex:commandButton action="{!onSubmitAll}" value="Save" onclick="if(!approvalReq()) return false;" style="width:60px">
                    <apex:actionStatus id="status">
                        <apex:facet name="start">
                            <div class="outerCls"></div>
                            <div class="innerCls">
                                Processing...
                            </div>
                        </apex:facet>
                    </apex:actionStatus>                   
                    <style>
                         .innerCls{
                               left:50%;
                               top:50%;
                               position:fixed;
                         }
                         .outerCls{
                             top: 0px;
                            left: 0px;
                            position: absolute;
                            background-color: #CCC;
                            opacity: 0.40;
                            width: 100%;
                            height: 100%;
                        }
                    </style>
                </apex:commandButton>

Regards
Lance Cresswell
Swati GSwati G
Hi Lance,

Please modify your code as below: 
<apex:commandButton action="{!onSubmitAll}" value="Save" onclick="if(!approvalReq()) return false;" style="width:60px" status="status">

                </apex:commandButton>

<apex:actionStatus id="status">
                        <apex:facet name="start">
                            <div class="outerCls"></div>
                            <div class="innerCls">
                                Processing...
                            </div>
                        </apex:facet>
                    </apex:actionStatus>                 
                    <style>
                         .innerCls{
                               left:50%;
                               top:50%;
                               position:fixed;
                         }
                         .outerCls{
                             top: 0px;
                            left: 0px;
                            position: absolute;
                            background-color: #CCC;
                            opacity: 0.40;
                            width: 100%;
                            height: 100%;
                        }
                    </style>

Regards,
Swati
LanceCresswellLanceCresswell
Hi,

Still don't understand how the actionstatus on the commandbutton ensures the ApprovalRequired action Method called by the actionsupport onchange event on the inputField has finished before the approvalReq js function is called by the onclick event on the commandbutton.

Surely this actionstatus is just supporting the onSubmitAll AJAX action?

Regards
Lance Cresswell
Swati GSwati G
You will need to specify status is actionsupport. ActionStaus will show loading text to the user which wont allow user to click any thing on page.

Here is one page you can see.: http://testsiteatpsl-developer-edition.ap1.force.com/swatig16__TestVFPage

Code: 

  <apex:outputLabel value="User Input 1"></apex:outputLabel>
        <apex:inputText >
             <apex:actionSupport event="onchange" action="{!onChangeEvent}" status="status" reRender="dummy"/>
        </apex:inputText>
        <apex:outputLabel value="User Input 2"></apex:outputLabel>
        <apex:selectList size="1">
            <apex:selectOption itemValue="Test1" itemLabel="Test1"></apex:selectOption>
            <apex:selectOption itemValue="Test2" itemLabel="Test2"></apex:selectOption>
            <apex:actionSupport event="onchange" action="{!onChangeEvent}" status="status" reRender="dummy"/>
        </apex:selectList>
   
        <apex:commandButton action="{!onSubmitAll}" value="Save"  style="width:60px" />

<apex:actionStatus id="status">
        <apex:facet name="start">
            <div class="outerCls"></div>
            <div class="innerCls">
                Processing...
            </div>
        </apex:facet>
    </apex:actionStatus>                
    <style>
         .innerCls{
               left:50%;
               top:50%;
               position:fixed;
         }
         .outerCls{
             top: 0px;
            left: 0px;
            position: absolute;
            background-color: #CCC;
            opacity: 0.40;
            width: 100%;
            height: 100%;
        }
    </style>
This was selected as the best answer
LanceCresswellLanceCresswell
Really appreciate all your help and patience - it works now.