Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

Quick background: I've already tried disabling onclick via apex, but my disable does not execute fast enough in the UI.

I'm trying to incorporate jQuery in my VF page code so that a button is disabled upon the first click. How can I incorporate this code I found online: http://stackoverflow.com/questions/5445431/jquery-disable-submit-button-on-form-submission

to my current VF code:

    <apex:pageBlock mode="edit" rendered="{!passesCheck}" id="mainBlock">
        <apex:pageBlockButtons >
            <apex:actionStatus id="saving">
                <apex:facet name="start" ><apex:image url="{!$Resource.loading}" /></apex:facet>
                <apex:facet name="stop" >
                    <apex:commandButton action="{!save}" status="saving" disabled="{!stopSave}" 
                                        value="{!IF(OR(isAddOn, currencyUpdate), 'Update', 'Create')} Renewal" />
                </apex:facet>
            </apex:actionStatus>
            <apex:commandButton value="Cancel" action="{!cancel}" />
        </apex:pageBlockButtons> 
share|improve this question
add comment

4 Answers 4

up vote 5 down vote accepted

Just for clarification, the reason that this is happening in your page is not that it doesn't execute 'fast enough' but instead the intended behaviors are occurring in the wrong order.

The manner in which I normally accomplish this behavior is like this... a button on the page calls a function (of my own) which first calls the actionFunction to post the data, then disables the buttons. The actionFunction is defined with an oncomplete="" script to call another function in the page to re-enable the buttons in the page when the ajax post is finished.

In this example 'addNewRow' starts the process via the button click and 'addNewRowComplete' is called when the actionFunction is finished.

Simply adding the css class 'btnDisabled' will make the button(s) appear to the user as disabled, but will in fact still be clickable causing the form to post again.

This code should be a functional example as written though you should change the function names to fit your needs.

<apex:page>
    <script>
    // function to control the native css style 
    // and the addition and removal of the disabled attribute on the buttons
    function buttonsEnabled(enable) {
        var $buttons = jQuery('.btn'); // find all buttons in the page
        if (enable === false) {
            $buttons.toggleClass('btnDisabled', true).attr('disabled', 'disabled');
        } else {
            $buttons.toggleClass('btnDisabled', false).attr('disabled', null);
        } 
    }

    // function called by the commandButton
    function addNewRow() {
        // make the ajax post via the actionFunction definition by calling the AF
        // this is case sensitive, match the name of the actionFunction
        doTheSave(); 

        // _then_ disable the buttons on the page
        buttonsEnabled(false);

        // return false to prevent the form from performing the button's click
        // behavior in addition to this function call. note that the onclick 
        // statement of the button returns this false value to the browser.
        return false;
    }

    function addNewRowComplete() {  
        // re-enable the buttons on the page after the actionFunction is finished
        buttonsEnabled(true);   
    }

    </script>


    <apex:form>
    <!-- somewhere in your form -->
    <apex:actionFunction name="doTheSave" action="{!save}" status="saving" rerender="messages" oncomplete="addNewRowComplete();"></apex:actionFunction>

    <!-- your normal button definition with the addition of the onclick script -->
    <apex:commandButton action="{!save}" status="saving" disabled="{!stopSave}" 
        value="{!IF(OR(isAddOn, currencyUpdate), 'Update', 'Create')} Renewal" 
        onclick="return addNewRow();" />
    </apex:form>
</apex:page>

Hope this helps get you going in the right direction!

share|improve this answer
add comment

Salesforce already disables the buttons on standard page layouts when a Save is selected. I took a look at their main.js javascript file, and it looks like the following function is what is called when a Save is clicked:

DetailPage.prototype.save = function () {
    if (!this.saving && this.editMode) {
        this.saving = !0;
        for (var a = 0; a < this.editButtons.length; a++){  
            this.editButtons[a].className = "btnDisabled";
            this.editButtons[a].value = LC.getLabel("Buttons", "saving");
        }
        this.inlineEditData.save();
    }
};

So, it looks like simply setting the buttons class to "btnDisabled" should be exactly what you want to do. Salesforce changes the label of the button as well using a different Javascript file that loads separately (en_US.js in this case). That javascript looks like:

LC.labels = {
...
'Buttons': {
    'cancel': 'Cancel',
    'close': 'Close',
    'confirm': 'Confirm',
    'create_new': 'Create New {0}',
    'customize': 'Customize',
    'del': 'Delete',
    'delete': 'Delete',
    'dont_save': 'Don\'t Save',
    'edit': 'Edit',
    'go': 'Go!',
    'help': 'Help',
    'hide': 'Hide Details',
    'ins': 'Insert',
    'new': 'New',
    'no': 'No',
    'ok': 'OK',
    'page_help': 'Help for this Page',
    'quick_save': 'Quick Save',
    'refreshData': 'Refresh',
    'remove': 'Remove',
    'save': 'Save',
    'saveAs': 'Save As',
    'save_and_close': 'Save & Close',
    'save_and_new': 'Save & New',
    'saving': 'Saving...',
    'search': 'Search',
    'send': 'Send',
    'show': 'Show Details',
    'submit': 'Submit',
    'undo': 'Undo',
    'yes': 'Yes'
},
...

}

This utilizes the following CSS from common.css:

.btnDisabled {
    font-family:'Verdana','Geneva',sans-serif;
    background-image:url("/img/bgButtonDisabled.gif");
    background-repeat:repeat-x;
    background-position:left top;
    border-right:1px solid #999999;
    border-bottom:1px solid #999999;
    border-top:1px solid #CCCCCC;
    border-left:1px solid #CCCCCC;
    font-size:80%;
    color:#C1C1C1;
    padding:0 3px 1px 3px;
    cursor:default;
    font-weight: bold

}

You may be able to do something along the lines of:

onClick="this.className='btnDisabled';this.value=LC.getLabel('Buttons"', 'saving');"

That should properly add internationalization too I believe. Now, this is all theory and all of these Javascript files may not load on non-standard pages, but either way you should be able to adapt this. Unfortunately, this still doesn't solve your issue on disabling the actual click. Now you can do this a few ways, adding a Javascript file that you can then use to save a variable. You could also just add a hidden field to store it as well:

<input type="hidden" value="true" id="firstButtonClick"/>

This would be my approach. Using all of this (theoretically), you should be able to use:

<apex:commandButton action="{!save}" onclick="this.className='btnDisabled';this.value='LC.getLabel('Buttons', 'saving');if(document.getElementById('firstButtonClick').value == 'true'){document.getElementById('firstButtonClick').value='false';return true;}else{return false;}"/>
<input type="hidden" value="true" id="firstButtonClick"/>

This may or may not be the best solution (or even a working once since I didn't test it all out fully), but this hopefully puts you in the right direction.

share|improve this answer
1  
Peter Knolle just showed me this - boards.developerforce.com/t5/Visualforce-Development/… - This should help you out too –  Jesse Altman Jan 14 '13 at 19:14
add comment

Instead of jQuery, can you simply add an normal JavaScript onclick a la:

onclick='this.disabled = true'
share|improve this answer
1  
Performing this action will prevent the button and its value from being part of the form data which is posted, which will subsequently prevent the apex class from being able to determine which button was clicked and which action to perform. –  Mark Pond Jan 14 '13 at 18:33
    
Right... that's why I need to use JQUERY –  Eric Luu Jan 14 '13 at 18:41
add comment

Add a styleClass to your command button (for this example, let's call it "cmdButton"), then you can use that for your jquery selector:

$('.cmdButton').click(function() {
     $(this).attr('disabled', 'disabled');
     $(this).parents('form').submit() )}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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