Background: I have a requirement where we need to display a VF page on the Contact object that indicates whether or not a contact has had their contact information verified within the last 14 days or not. If the contacts Last_Verification_Date__c is more than 14 days prior to Today, I render one outputPanel that says "Customer Needs Verification". When you mouse over that portion of the VF page, a "Verify" commandLink appears. When you press this "Verify" link, I want to re-render the Visualforce page and show that the contact is now verified, without forcing a page load.
Screenshot on Unverified Contact before Mouse Over:
Screenshot on Unverified Contact on Mouse Over:
Screenshot on VERIFIED Contact after pressing Verify button and MANUALLY refreshing the page:
From the example screens above, I hope you can see what I am trying to achieve. Basically - the contacts are all not verified if we haven't checked their info in the last 14 days. When they aren't verified I render Image 1, and when you mouse over it you get the button in Image 2. When you click the button, the Last_Verification_Date__c field DOES get updated correctly in the databse, but the rerender doesn't do anything. The only way to see Image 3 is if you manually reload the page after pressing Verify.
I originally attempted to assign ids to each of the outputPanels separately and then do a rerender="Id1,Id2" on my commandLink, but I found this blog post by Bob Buzzard where he notes that you can't do it like that because the reRender is trying to render something that was never rendered in the first place (because it didn't meet render conditions): http://bobbuzzard.blogspot.co.uk/2011/02/visualforce-re-rendering-woes.html
His solution is to wrap both of my dynamically rendered outputPanels inside another parent outputPanel, assign the parent panel an Id, and then do the reRender to that Id instead. I tried that too, but still it will not rerender.
At this point I'm not sure what's wrong. Is it not working because my commandLink is inside of the panel that is being rerendered? Is there a problem with the way my rerender is structured? Is my render condition for the 2 different alert messages not being updated correctly/returning the right value from the controller during rerender?
I'm not really sure how to debug rerender, so I'm at a loss - any thoughts are appreciated.
Code:
Page:
<apex:page standardController="Contact" extensions="ContactCTRL_XT">
<script src="https://use.fontawesome.com/305c6a828e.js"></script>
<style tyle="text/css">
.hide {display:none;}
.show {display:none;border:1px solid #ccc;background-color:green;color:white;font-weight:bold;border-radius: 6px;margin-top:0px;margin-bottom:0px;padding:6px;}
.verify {display:inline-block;border:1px solid #ccc;border-radius: 6px;margin-top:0px;margin-bottom:0px;padding:10px;margin-left:-120px;}
.verify:hover .show {display:inline-block;}
span.needToVerify {display:inline-block;font-weight:bold;font-size:1.5em;color:red;margin-top:5px}
span.verifiedText {display:inline-block;font-weight:bold;font-size:1.5em;color:green;margin-top:5px}
.isVerified {border:1px solid #ccc;border-radius: 6px;margin-top:0px;margin-bottom:0px;padding:10px;display:inline-block;margin-left:0px;}
</style>
<apex:form >
<div style="width:100%;text-align:center">
<apex:outputPanel id="refreshMe">
<apex:outputPanel rendered="{!!isVerified}" id="needToVerify">
<div class="verify">
<apex:commandLink action="{!verifyContact}" rerender="refreshMe">
<div class="show">
Verify
</div>
</apex:commandLink>
<span class="fa-stack fa-lg" style="color:red;vertical-align:middle;margin-top:-7px">
<i class="fa fa-circle-thin fa-stack-2x"></i>
<i class="fa fa-exclamation fa-stack-1x"></i>
</span>
<span class="needToVerify">Contact Needs Verification</span>
</div>
</apex:outputPanel>
<apex:outputPanel rendered="{!IsVerified}" id="Verified">
<div class="isVerified">
<span class="fa-stack fa-lg" style="color:green;vertical-align:middle;margin-top:-7px">
<i class="fa fa-circle-thin fa-stack-2x"></i>
<i class="fa fa-check fa-stack-1x"></i>
</span>
<span class="verifiedText">Contact Verified</span>
</div>
</apex:outputPanel>
<apex:outputPanel rendered="{!(contact.account.Password__c != NULL) && (contact.account.Zuora__Active__c == 'Yes')}">
<c:PasswordRequiredBanner Password="{!contact.account.Password__c}" />
</apex:outputPanel>
</apex:outputPanel>
</div>
</apex:form>
</apex:page>
Controller Extension:
public with sharing class ContactCTRL_XT {
Contact cont {get;set;}
public ContactCTRL_XT(ApexPages.StandardController stdController) {
stdController.addFields(new String[]{
'FirstName',
'LastName',
'Contact_Verified__c',
'Last_Verification_Date__c'
});
this.cont = (Contact)stdController.getRecord();
}
public Boolean getIsVerified(){
Date contactDate = cont.Last_Verification_Date__c;
Date todaysDate = Date.today();
if(contactDate == null){
return false;
}
else{
Date contactDatePlus14 = cont.Last_Verification_Date__c + 14;
if(contactDatePlus14 >= todaysDate){
return true;
}
else{
return false;
}
}
}
public PageReference verifyContact(){
Contact tempContact = new Contact(Id = cont.Id,
Last_Verification_Date__c = Date.today(),
Contact_Verified__c = true
);
update tempContact;
return null;
}
}