function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
EXRADMEXRADM 

Hide or Disable a Button After Click

On a standard Salesforce edit page, when the save button is clicked, the button immediately grays out and prevents the user from clicking the button multiple times.  I'm trying to get the same effect on a VFP but I am having no luck.  Has anybody already done this?  I don't know if it's pertinent, but my save button is calling a method called Save in a custom controller.

 

 

<apex:pageBlockButtons > <apex:commandButton action="{!Save}" value="Save" id="saveBtn" /> </apex:pageBlockButtons>

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
EXRADMEXRADM

I should have posted this forever ago - but this is what my final solution ended up looking like.  Works wonderfully.

 

The Javascript on the page: 

 

 

<script type="text/javascript">

function KillSaveButton(){

var obj= document.getElementById('cmdSave')

var obj2= document.getElementById('cmdSave2')

 

obj.style.visibility = 'hidden';

obj2.style.visibility = 'hidden';

}

 

function KillRetryButton(){

var obj= document.getElementById('cmdRetry')

var obj2= document.getElementById('cmdRetry2')

 

obj.style.visibility = 'hidden';

obj2.style.visibility = 'hidden';

}

 

function KillLostOppButton(){

var obj= document.getElementById('cmdLost')

var obj2= document.getElementById('cmdLost2')

 

obj.style.visibility = 'hidden';

obj2.style.visibility = 'hidden';

}

</script>

 

 The actionFunctions:

 

<apex:actionFunction name="RunSave" action="{!mySave}" reRender="ErrMsgs, RedirectTO, Buttons, Buttons2" oncomplete="RedirectOnSuccess('Save');" status="otherSaveStatus" />

 

<apex:actionFunction name="RunRetry" action="{!Retry}" reRender="ErrMsgs, RedirectTO, Buttons, Buttons2" oncomplete="RedirectOnSuccess('Retry');" status="RetryStatus" />

 

The buttons:

<!-- Buttons at the top of the page -->

<apex:outputPanel id="Buttons">

<center>

<input type="button" value="Save" id="cmdSave" onclick="KillSaveButton();RunSave();" class="btn" style="{!ShowSaveButton}" />

<input type="button" value="Retry" id="cmdRetry" onclick="KillRetryButton();RunRetry();" class="btn" style="{!ShowRetryButton}" />

<apex:commandButton action="{!SaveLostOppty}" value="Lost Opportunity" rendered="{!ShowLostOpptyButton}" />

</center>

</apex:outputPanel>

 

<!-- Buttons at the bottom of the page -->

<apex:outputPanel id="Buttons2">

<hr />

<center>

<input type="button" value="Save" id="cmdSave2" onclick="KillSaveButton();RunSave();" class="btn" style="{!ShowSaveButton}" />

<input type="button" value="Retry" id="cmdRetry2" onclick="KillRetryButton();RunRetry();" class="btn" style="{!ShowRetryButton}" />

<apex:commandButton action="{!SaveLostOppty}" value="Lost Opportunity" rendered="{!ShowLostOpptyButton}" />

</center>

</apex:outputPanel>

 I believe that is all the pertinent code.  Let me know if any clarification is needed.

 

 

 

Message Edited by EXRADM on 06-18-2009 08:09 AM

All Answers

Kirk F.ax361Kirk F.ax361

You can get this effect easily.  You already know about ActionStatus, which gives the user feedback on the status of an AJAX call.  Usually, we put a spinner image or some other sort of progress indicator in there.

 

Why not put your button as well?

 

Try this:

 

<apex:actionStatus id="mySaveStatus"> <apex:facet name="stop"> <apex:commandButton value="Save" action="{!doSave}" status="mySaveStatus" rerender="currentSiteDisplay"> </apex:commandButton> </apex:facet> <apex:facet name="start"> <apex:commandButton value="Saving..." disabled="true" action="{!doSave}" status="mySaveStatus" rerender="currentSiteDisplay"> </apex:commandButton> </apex:facet>

 

1) When the page renders, the actionStatus mySaveStatus has not started, so the components in the "stop" facet are rendered.  This means your "Save" button appears.

 

2) When the user clicks the "Save" button, the status of "mySaveStatus" is set to "start" until the ajax call is finished.  This means the "Save" button is hidden, and the disabled "Saving..." button is shown.  

 

3) When the call finishes, then the greyed-out "Saving..." button disappears again, replaced by the "Save" button. 

 

This is visually identical to the way some of the salesforce-native buttons appear, so it can be a good way to have your custom code keep the same styling and behavior when clicked.

 

(Note:  you'll see that the disabled "Saving..." button has action and status and re-render.  Why, if it's never going to be clicked?  Because I'm lazy.  I just copy/pasted the "Save" button, changed it's name to "Saving..." and added the disabled flag.)

 

 

EXRADMEXRADM
Well, that does solve the button issue, however, using that solution makes it so that my error messages don't show up.  For example, if I tried to save an Opportunity without the required Close Date, I could click the button, validation would fail and nothing would be saved, but the page doesn't show any errors.
Kirk F.ax361Kirk F.ax361

<apex:pageMessages/>

 

can be useful to show any error messages, no matter where they come from...  Just remember to refresh the component that contains this tag, so any Ajax errors appear.  Basically, if parts of your page need to be updated after the data returns (or the error does), don't forget to list them in the "rerender" tag of this button, so they get updated.

 

Message Edited by Kirk F on 03-02-2009 09:50 AM
Message Edited by Kirk F on 03-02-2009 09:51 AM
EXRADMEXRADM

Hmmm...I thought I was already doing that.  Maybe I'm missing something dumb...wouldn't be the first time.  Here's what the code looks like:

 

 

<apex:pageBlock title="Opportunity Detail" mode="edit" id="MainPageBlock"> <apex:pageMessages id="myMessages" /> <apex:pageBlockButtons > <apex:actionStatus id="mySaveStatus"> <apex:facet name="stop"> <apex:commandButton value="Save" action="{!Save}" status="mySaveStatus" rerender="myMessages"> </apex:commandButton> </apex:facet> <apex:facet name="start"> <apex:commandButton value="Saving..." disabled="true" action="{!Save}" status="mySaveStatus" rerender="myMessages"> </apex:commandButton> </apex:facet> </apex:actionStatus> </apex:pageBlockButtons>// the rest of my page</apex:pageBlock>

 

 

 

sapsap

Hi,

 

First of all I want to thank you for your post.

It helped me alot.

 

But I have one issue using this code.

Im using pageblockbuttons which displays the 'Save' button on the top and bottom of the page.

 

Using this code it is graying out the top button, not the bottom one.

 

Im I missing something.

Can you please help me resolve this.

 

Thanks in advance

 

Swapna

Kirk F.ax361Kirk F.ax361

XRADM,

Hmm... try a simple page, where the apex:messages component is refreshed successfully.  Then move your button into the wrapper as suggested here, and see if that is what breaks it.  If so, then you have a great "before" and "after" pair of code blocks to submit to support as a case.  It's not immediately apparent to me what the problem could be there.  Sorry.

 

sap,

I never thought of doing this to pageBlockButtons.  Cool idea!  As you see, with pageBlockButtons you define them once but they appear twice.  I think it's a bug that the code you write is applied to the first, but not to the next.  You can submit this to support.  Maybe it will motivate them to have the pageBlockButtons in apex pages get the same styling as pageBlockButtons in salesforce pages, so we won't have to do this extra work to get the greyed-out button style when they are clicked!  ;-)

a_Ba_B

 

You can do this by using javascript. Put an onlclick javascript function and create an action function for the controller method. This is what OnClick function looks like...

 

function SubmitOnClick(bttnSubmit) { try{ SubmitDeal(); // This is the ActionFunction bttnSubmit.disabled=true; bttnSubmit.setAttribute("class" , "btnDisabled"); }catch(err){ alert(err); 

} 

     }

 

In your action function add oncomplete event ... this will refresh the entire page after the process ends.

uppalauppala

Hi Kirk,

 

thank you very much 

Message Edited by uppala on 06-17-2009 03:35 PM
Kirk F.ax361Kirk F.ax361
a_B, that's a good idea!  If anyone can confirm a_B's idea works for them, and post the complete code to an example VisualForce page (using the techniques in this thead), that could be a good summary of this discussion.
EXRADMEXRADM

I should have posted this forever ago - but this is what my final solution ended up looking like.  Works wonderfully.

 

The Javascript on the page: 

 

 

<script type="text/javascript">

function KillSaveButton(){

var obj= document.getElementById('cmdSave')

var obj2= document.getElementById('cmdSave2')

 

obj.style.visibility = 'hidden';

obj2.style.visibility = 'hidden';

}

 

function KillRetryButton(){

var obj= document.getElementById('cmdRetry')

var obj2= document.getElementById('cmdRetry2')

 

obj.style.visibility = 'hidden';

obj2.style.visibility = 'hidden';

}

 

function KillLostOppButton(){

var obj= document.getElementById('cmdLost')

var obj2= document.getElementById('cmdLost2')

 

obj.style.visibility = 'hidden';

obj2.style.visibility = 'hidden';

}

</script>

 

 The actionFunctions:

 

<apex:actionFunction name="RunSave" action="{!mySave}" reRender="ErrMsgs, RedirectTO, Buttons, Buttons2" oncomplete="RedirectOnSuccess('Save');" status="otherSaveStatus" />

 

<apex:actionFunction name="RunRetry" action="{!Retry}" reRender="ErrMsgs, RedirectTO, Buttons, Buttons2" oncomplete="RedirectOnSuccess('Retry');" status="RetryStatus" />

 

The buttons:

<!-- Buttons at the top of the page -->

<apex:outputPanel id="Buttons">

<center>

<input type="button" value="Save" id="cmdSave" onclick="KillSaveButton();RunSave();" class="btn" style="{!ShowSaveButton}" />

<input type="button" value="Retry" id="cmdRetry" onclick="KillRetryButton();RunRetry();" class="btn" style="{!ShowRetryButton}" />

<apex:commandButton action="{!SaveLostOppty}" value="Lost Opportunity" rendered="{!ShowLostOpptyButton}" />

</center>

</apex:outputPanel>

 

<!-- Buttons at the bottom of the page -->

<apex:outputPanel id="Buttons2">

<hr />

<center>

<input type="button" value="Save" id="cmdSave2" onclick="KillSaveButton();RunSave();" class="btn" style="{!ShowSaveButton}" />

<input type="button" value="Retry" id="cmdRetry2" onclick="KillRetryButton();RunRetry();" class="btn" style="{!ShowRetryButton}" />

<apex:commandButton action="{!SaveLostOppty}" value="Lost Opportunity" rendered="{!ShowLostOpptyButton}" />

</center>

</apex:outputPanel>

 I believe that is all the pertinent code.  Let me know if any clarification is needed.

 

 

 

Message Edited by EXRADM on 06-18-2009 08:09 AM
This was selected as the best answer
minkesh_patelminkesh_patel

I have requirement that when i will click on button Create dispute at that time value of that button must be changed and it will be disable and after called action function it will call apexmessage and one ok button. when we click on that button page will be redirected to the transaction.

 

I have written code for disabled button but it is not working in mozzilla and in IE it will be disabled but not redirected.any suggestion would be appreciated.

 

 

 function afterSubmit(){
        
            document.getElementById("pg:frm:pb:pbb:btnexe").value = "Executing...";
            document.getElementById('{!$Component.frm.pb.pbb.btnexe}').disabled = true;
            
         }

roycastilloroycastillo

cn anybody help me on my application requirement? i need to hide a custom button named "Submit" if the status is already Submitted...note that the status field is also a custom one.

 

thanks a lot

RReddyRReddy

Hi all,

 

i have designed VF page with Save and Cancel buttons.On Clicking Save button, Cancel button also need to go into Saving mode, similar to Salesforce standard page.

 

My Requirement is : 

 

On clicking Save button ,we need to disable save a& cancel buttons and need show Saving text for both the buttons .

 

Thanks,

Ramana

Ravan557Ravan557
VisualForce Code

<apex:page controller="hidebuttons">
  <apex:form id="od">
    <apex:pageBlock >
    <apex:pageBlockSection >
     <apex:commandButton value="Button1" action="{!A1}" rendered="{!b1}" reRender="od"/>
     <apex:commandButton value="Button2" action="{!A2}" rendered="{!b2}" reRender="od"/>
     </apex:pageBlockSection>
     </apex:pageBlock>
  </apex:form>
</apex:page>


Controller Code

public with sharing class hidebuttons {

    public Boolean b1 {get; set; }
    public Boolean b2 {get; set; }
    
    public hidebuttons(){ 
    b1 = true;
    b2 = true;
    }
    
    public PageReference A1() {
    b1 = false;
    b2 = true;
        return null;
    }

    public PageReference A2() { 
    b1 = true;
    b2 = false;
        return null;
    }    
}
Mooda MayuMooda Mayu
I know it is too late :), however, thank you for the code. It helped me in solving my issue...@Ravan557