3

When I double click on the output field and try to change the field value. The updated value is not getting saved when i directly click on save button.

Instead, In order to save record I need to click on screen first and then save. In this case record gets saved.

But I don't want to use second option as it is not efficient.

Can you all please suggest me a solution for this?

<apex:page standardController="Employee__c" extensions="HRMSController" action="{!checkSession}" showHeader="false" sidebar="false" tabStyle="Account" docType="html-5.0"> 
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css" />
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>    
<script>
    j$ = jQuery.noConflict();
    function phonenumber(inputtxt){
        var phoneno = /^\d{10}$/;
        if(inputtxt.value.match(phoneno)){
            return true;
        }else{
            alert("Enter 10 digit phone No.");
            j$('input[name$="mobileid"]').val('').focus();
            return false;
        }
    }    
</script>    
<apex:stylesheet value="{!$Resource.HRMSStyle}"/>
<style>
    #menu{
    float:none !important;
    }
    .customTable{
    margin-left:35px !important;
    width: 75% !important;
    }
    .pushbtn{
    margin-left:35px !important;
    } 
    .apexp .bPageBlock .detailList { width: 94%; }
</style>
<apex:include pageName="HRMSHeader"/>
<apex:form enctype="multipart/form-data" html-novalidate="novalidate" >

    <apex:pageMessages ></apex:pageMessages>         
    <apex:pageBlock >
        <apex:pageBlockSection >
            <apex:commandButton value="Add Candidate" action="{!hideMethod}" styleClass="pushbtn" />
        </apex:pageBlockSection>
    </apex:pageBlock>


    <apex:outputPanel >
        <apex:pageBlock >        
            <apex:pageBlockButtons location="Bottom" >
                <apex:commandButton value="Save" action="{!saveMethod1}" styleClass="pushbtn" onclick="phonenumber()"  />                       
                 <apex:commandButton value="Cancel" immediate="true" styleClass="pushbtn"/>
            </apex:pageBlockButtons>
            <br/>
            <div class="pageHeaderHRMS" style="padding-left: 2% !important; margin-left: 33px; width: 75%;">Details of Referral Employee</div>
            <br/> 
            <apex:pageBlockSection columns="2" collapsible="false" >    
                <apex:inputField value="{!cand.Name}" required="true" />
                <apex:inputField value="{!cand.Experience__c}" required="true" /> 
                <apex:inputField value="{!cand.Mobile_No__c}" required="true" id="mobileid" onchange="phonenumber(this)"/> 
                <apex:inputField value="{!cand.Email_ID__c}" required="true" />     
                <apex:inputField value="{!cand.Technology__c}" style="margin-right: 36px;margin-left: -3px;" /> 
                <apex:inputField value="{!cand.Location__c}" required="true" />
                <apex:outputLabel value="Upload Resume" for="fileToUpload" style="margin-left:550px;margin-left: 106px;"></apex:outputLabel>        
                <apex:inputFile required="true" style="width:100%;margin-left: -430px;" id="fileToUpload" value="{!myAttachment.Body}" filename="{!myAttachment.Name}" contentType="contentType" />             
          </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:outputPanel>

    <apex:outputPanel >
        <apex:pageBlock >
           <apex:pageBlockTable value="{!Candidate}" var="cand" styleClass="customTable">
            <apex:column headerValue="Action">
                  <apex:commandLink style="color:#72d4ca;" value="Delete" action="{!deleteRecord}">
                      <apex:param name="ruleID" value="{!cand.id}"/>
                  </apex:commandLink> &nbsp;|&nbsp;
                  <apex:commandLink style="color:#72d4ca;" value="Save"  action="{!EmpReferralSave}"> </apex:commandLink>

            </apex:column>       
            <apex:column headerValue="Name" value="{!cand.Name}"></apex:column>   
            <apex:column headerValue="Email" value="{!cand.Email_ID__c}"></apex:column>
            <apex:column headerValue="CreatedDate" value="{!cand.CreatedDate}"></apex:column>
            <apex:column headerValue="Technology" value="{!cand.Technology__c}"></apex:column>                  
             <apex:inlineEditSupport event="ondblClick" />  
            </apex:pageBlockTable>
        </apex:pageBlock>        
    </apex:outputPanel>

</apex:form>
</apex:page>

Controller:

 // Method for showing Referral Employee Form defined on "Add candidate" button
Public void hideMethod(){
   if (showflag == false){
     showtb1 = true;
   }else{
        showflag = false;
        showtb1 = true;
        showtb2 = false;
   }
}
// Employee Referral - Method fires on Save button
Public pagereference saveMethod1(){    
   showtb2=true;
   showtb1=false;
   showflag = true;
   PageReference pageRef=HRMSUtilClass.EmployeeReferralSave(cand,myAttachment,userid,isSaved,contentType,showflag,showtb2,showtb1,Candidate);
   Candidate = [Select id, Name, CreatedDate, Email_ID__c, Technology__c from Candidate__c WHERE Employee__c = : userid order by Id DESC];//Status__c, Employee__c, Experience__c


   return pageRef;       
}
// Cancel button to hide Referral Employee Form defined on "Cancel" Button
public PageReference cancelemployeeref(){ 
    PageReference pageRef = HRMSUtilClass.EmployeeReferralCancel(userid,showflag,showtb2,showtb1);
    return pageRef;
}

// Method to Delete Record from Candidate List
public PageReference deleteRecord(){
    ID rid = ApexPages.currentPage().getParameters().get('ruleID');
    PageReference pageRef = HRMSUtilClass.EmployeeReferralDeleteRecord(userid,rid);
    for(integer i=0;i<Candidate.size();i++)
    {
        if(Candidate[i].Id == rid ){

           Candidate.remove(i);
           break;
        }



    }


    pageRef.setRedirect(false);   
    return pageRef;
 }
// Method to Save Record from Candidate List
Public PageReference EmpReferralSave(){

    showtb1 = false;
    showtb2 = true;  

    PageReference pageRef = HRMSUtilClass.EmployeeReferralUpdate(Candidate,userid);
    return pageRef;
 }
  • If you post your code (Apex and VisualForce) then people will be able to help you, otherwise your question may be closed. – BarCotter Mar 4 '15 at 11:15
  • 2
    @BarCotter we can keep this open, I know that issue and can answer it. It's pretty clear, no code needed. Possible it's already answered here, I'm going to check that now. – Uwe Heim Mar 4 '15 at 11:44
  • @UweHeim - Looking forward to your answer. Have been facing the same issue and just wrote it up to a "Expected Feature Enhancement" :) – Eric Mar 4 '15 at 13:01
  • Try this . It might help salesforce.stackexchange.com/questions/3946/… – Kaw Sumit Mar 4 '15 at 13:10
  • @Eric and Vrushabh I have to distill it out of a lager "Visulaforce healthkeeping" JS-class - BUT if the answer from Kaw works, take that! - my workaround was way more complex, but I will provide it, too. – Uwe Heim Mar 4 '15 at 14:46
2

If Kaw's solution works, I would prefer his - my approach is way more complicated. At the time I did it, I found it necessary and considered this is a bug in Visualforce.

Basically I found two issues:

  • last edited value won't be saved: if the focus does not leave the input control (meaning it's still in editmode and the input controls are still visible), you have to click first somewhere else so that the input is loosing focus. Then the input controls will be hidden and work fine, but if you keep the focus on the control, the last field edited won't update correctly.
  • single-click event preselects text: if you change the event form onDblClick (default) to onClick, the text will be all preselected after you click into it and the controls appears. Even worse, the text is very hard to get deselected - simple clicks doesn't help. Need to move cursor with Keyboard, which really sucks.

The following is I distilled it out of a bigger Visulaforce fixing library but I hope the concepts will still become clear. I put JS and VF together for the sake of simplicity.

SFSEInlineEdit.cls

public class SFSEInlineEdit { 
    public list<sobject>            listItems               { get; set; }
    public list<wrap>               listWraps               { get; set; }
    public class wrap {
        public boolean              checked                 { get; set; }
        public sobject              item                    { get; set; }
    }
    public void listInit() {
        this.listUpdateWraps();
    }
    public PageReference listSave() {
        update listItems;
        this.listUpdateWraps();
        return null; 
    }
    public void listUpdateWraps() {
        this.listItems = Database.query( 'select Type, Name from Account' );
        this.listWraps = new list<wrap>();
        for(sobject item : this.listItems) {
            wrap wrap           = new wrap();
            wrap.item           = item;
            this.listWraps.add(wrap);
        }
    }
}

SFSEInlineEdit.page

<apex:page controller="SFSEInlineEdit" action="{!listInit}">  
    <apex:includeScript value="{!$Resource.jquery}"/>
    <script> 
        page = {
            afterUpdate: function() { var self = this; // this function should be part of a javascript tag which is re-renderd by action-functions to keep inline-editing fixed.
                self.inlineEdit.applyFix(); 
            },  
            inlineEdit: {
                applyFix: function() { var self = this;
                    $("form .inlineEditWrite").each(function(){
                        if($(this).find('.elfCellcheckImg').size()==0) {
                            $(this).attr("onclick",$(this).attr("onclick")+"; page.inlineEdit.activate(); ");
                            $(this).attr("onmouseover","return false;");
                            $(this).attr("onmouseout","return false;");
                        }
                    });
                },
                syncAllElements: function() { var self = this;
                    console.log("[elfPage] syncing inlineEdit fields...");
                    $('.inlineEditDiv input').each(function(){
                        console.log(this.id+" : "+$(this).val());
                        var c = sfdcPage.getInlineEditData(this.id);
                        c.closeCurrentField(null, !1);
                    });
                },
                activate: function() { var self = this;
                    $(".inlineEditWrite input").click( function(){ return false; });
                    $(".inlineEditWrite input").attr("onchange"," page.inlineEdit.syncAllElements();  "); 
                    $(".inlineEditWrite select").click( function(){ return false; });
                },
            },
        };
    </script>
    <apex:form id="listForm">
        <apex:pageBlock title="Test" >
            <apex:pageBlockButtons >
                <apex:commandButton value="Save" action="{!listSave}" rerender="listForm" /></apex:pageBlockButtons>
            <apex:pageBlockTable value="{!listWraps}" var="wrap" id="itemTable">
                <apex:column width="25px">
                    <apex:inputCheckbox value="{!wrap.checked}" styleClass="elfItemCheckbox"/>
                </apex:column>
                <apex:column width="100%">
                    <apex:outputField  value="{!wrap.item['Name']}"/>
                </apex:column>
                <apex:column width="1" >
                    <apex:outputField  value="{!wrap.item['Type']}"/>
                </apex:column>
                <apex:inlineEditSupport event="onClick" showOnEdit="saveButton,cancelButton" hideOnEdit="editButton" />
            </apex:pageBlockTable>
        </apex:pageBlock>
        <script> // this script is placed here to be re-executed after ajax may have re-rendered the form
            page.afterUpdate();
        </script>
    </apex:form>
 </apex:page>

Reproduction

  • Add these two files to a DE.
  • Put jquery in a StaticResource called jquery.
  • go to apex/SFSEInlineEdit in your browser
  • see the patched behavior

Play with line 52 in the VF page and disable/enable it and compare Salesforce Standard vs. Patched behavior.

page.afterUpdate();

In the unpatched mode invoke the issues

  • Click on an account name to engage Inline Edit ==> selection issue
  • Change Name and don't leave the edit, just click Save ==> data loss

enter image description here

| improve this answer | |
  • I made some necessary changes according to my code and It worked... – Vrushabh Jain Mar 9 '15 at 10:50
  • Super cool patch @Uwe Heim. I fixed the same issue with your patch. I'm just a beginner at jQuery and this patch gives me an insight of jQuery powers! Thanks – Logeswaran Udayakumar Mar 30 '15 at 13:19
  • @LogeswaranUdayakumar You're welcome, glad it helped! – Uwe Heim Mar 30 '15 at 17:43
5

I came up with a slightly different solution, that I think might be simpler and more self-contained for people looking for a fast fix. The solution involves adding a hidden text input field we can use Javascript to "click" before calling our action off of our controller extension. This causes the SF field to "commit" the change so our controller will see it when the action method fires. This resolved the problem for all the test cases I've found.

In this example, assume our MyExtension Apex class has a save() method to call. I moved the save() call to an action function and everything into a single Javascript function for easy use in the commandButton onclick property.

<apex:page standardController="Opportunity" id="page" sidebar="false" showHeader="false" extensions="MyExtension">
    <script>    
    // workaround is necessary since inline editing of VF picklist and/or checkboxes won't commit changes before action if the user doesn't "click out" first.  
    function focusAndSave() {
        document.getElementById('focusMe').click();
        saveFields();
    }
    </script>
    <apex:form >
        <apex:actionFunction action="{!save}" name="saveFields" reRender="errors, fields" />
        <apex:pageBlock >
            <apex:pageMessages id="errors" />        
            <apex:pageBlockButtons location="top" id="buttons">
                <apex:commandButton value="Save" onclick="focusAndSave();" >            
                <input type="text" id="focusMe" style="display:none" />
            </apex:pageBlockButtons>
            <apex:pageBlockSection columns="1" id="fields" >
                <apex:outputField value="{!Opportunity.My_Field__c}" >
                    <apex:inlineEditSupport event="ondblclick"  />          
                </apex:outputField>         
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>
| improve this answer | |
  • 1
    This should be the answer. It works; its easy and its fast – ministe2003 May 23 '16 at 15:16
  • Thanks . A lot. This is short sweet and crisp. Saved me a ton of code. – Pranay Jaiswal Oct 6 '16 at 3:58
0

Try using the below and i believe it should work with custom save operation as well.

<apex:outputField value="{!tempOpp.Name}" >
    <apex:inlineEditSupport showOnEdit="saveButton, cancelButton"
                            hideOnEdit="editButton" 
                            event="ondblclick" 
                            changedStyleClass="myBoldClass" 
                            resetFunction="resetInlineEdit"/>
</apex:outputField>
| improve this answer | |
  • We have similar code but it doesn't work. What is it we are missing? – RajeshShah Mar 16 '15 at 12:55
0

In save button call a javascript that changes the focus to any element and call save action:

Action:

<apex:actionFunction id="saveInline" name="saveInline" action="{!save}" oncomplete="window.location.reload()"/>

Save Button:

<apex:commandButton rendered="{!onEdit}" onmouseup="saveInlineJS()" value="Save"/>

Javascript function:

function saveInlineJS(){
    document.getElementById("theForm").focus();
    saveInline();
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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