I've created a VF page that displays 2 tables of contacts. The page contains command links "x" and "+". When X is clicked, it should be removed from the top table and placed on the bottom table. When + is clicked, the reverse should happen.
I have verified the functionality. My issue is that the tables are not re-rendered after the action is performed.
VF Page (updated to show final product since there's no reason to archive broken code):
<apex:page standardController="Case_Contact__c" recordSetVar="passThrough" extensions="CaseContactControllerHelper">
<apex:form id="form">
<apex:pageBlock id="pageBlock" title="Add Multiple Case Contacts">
<apex:pageBlockButtons >
</apex:pageBlockButtons>
<apex:outputPanel id="container">
<apex:pageBlockSection columns="1" title="Case Contacts"
id="CCSection" collapsible="False">
<apex:pageBlockTable value="{!CaseContacts}" var="CaseContact" id="CCTable">
<apex:column headerValue="">
<apex:commandLink value="X" action="{!DeleteCaseContact}" style="color:red;text-decoration:none;"
rerender="container" immediate="true">
<apex:param assignTo="{!ToDo}" value="{!CaseContact.Id}" name="{!CaseContact.Id}"/>
</apex:commandLink>
<!--<apex:outputText value="X" style="color:red"/>
<apex:actionSupport event="onclick" action="{!DeleteCaseContact}" rerender="container">
<apex:param assignTo="{!ToDo}" value="{!CaseContact.Id}" name="{!CaseContact.Id}"/>
</apex:actionSupport>-->
</apex:column>
<apex:column headerValue="First Name">
<apex:inputField value="{!CaseContact.First_Name__c}" style="width:100px;" rendered="{!ISNULL(CaseContact.Contact__c)}"/>
<apex:outputField value="{!CaseContact.First_Name__c}" style="width:100px;" rendered="{!NOT(ISNULL(CaseContact.Contact__c))}" />
</apex:column>
<apex:column headerValue="Last Name">
<apex:inputField value="{!CaseContact.Last_Name__c}" style="width:100px;" rendered="{!ISNULL(CaseContact.Contact__c)}"/>
<apex:outputField value="{!CaseContact.Last_Name__c}" style="width:100px;" rendered="{!NOT(ISNULL(CaseContact.Contact__c))}" />
</apex:column>
<apex:column headerValue="Email">
<apex:inputField value="{!CaseContact.Email__c}" style="width:200px;" rendered="{!ISNULL(CaseContact.Contact__c)}"/>
<apex:outputField value="{!CaseContact.Email__c}" style="width:200px;" rendered="{!NOT(ISNULL(CaseContact.Contact__c))}" />
</apex:column>
</apex:pageBlockTable>
</apex:pageBlockSection>
<apex:pageBlockSection columns="1" title="Account Contacts"
id="ACSection" collapsible="False">
<apex:pageBlockTable value="{!AccountContacts}" var="AccountContact" id="ACTable">
<apex:column headerValue="">
<apex:commandLink value="+" action="{!CreateCaseContact}" style="color:Blue;text-decoration:none;"
rerender="container" immediate="true">
<apex:param assignTo="{!ToDo}" value="{!AccountContact.Id}" name="{!AccountContact.Id}"/>
</apex:commandLink>
</apex:column>
<apex:column headerValue="First Name">
<apex:outputField value="{!AccountContact.FirstName}" style="width:100px;"/>
</apex:column>
<apex:column headerValue="Last Name">
<apex:outputField value="{!AccountContact.LastName}" style="width:100px;"/>
</apex:column>
<apex:column headerValue="Email">
<apex:outputField value="{!AccountContact.Email}" style="width:200px;"/>
</apex:column>
</apex:pageBlockTable>
</apex:pageBlockSection>
</apex:outputPanel>
</apex:pageBlock>
</apex:form>
</apex:page>
Controller Extension (updated to show final product since there's no reason to archive broken code):
public class CaseContactControllerHelper {
private Case Parent;
public List<Case_Contact__c> CaseContacts;
public List<Contact> AccountContacts;
public List<Id> Exclude;
public Id ToDo {get;set;}
public CaseContactControllerHelper(apexPages.StandardSetController stdCon) {
Parent = [SELECT Id, AccountId FROM Case
WHERE Id=:ApexPages.currentPage().getParameters().get('id')];
setCaseContacts();
setAccountContacts();
}
public pagereference DeleteCaseContact() {
Delete [SELECT Id FROM Case_Contact__c WHERE Id = :ToDo];
setCaseContacts();
setAccountContacts();
return Null;
}
public pagereference CreateCaseContact() {
INSERT new Case_Contact__c(Case__c=Parent.Id,Contact__c=ToDo);
setCaseContacts();
setAccountContacts();
return Null;
}
private void setAccountContacts() {
this.AccountContacts = [SELECT FirstName, LastName, Email, Phone FROM Contact
WHERE AccountId = :Parent.AccountId AND Id NOT IN :exclude];
}
public List<Contact> getAccountContacts() {
return this.AccountContacts;
}
private void setCaseContacts() {
this.CaseContacts = [SELECT First_Name__c, Last_Name__c, Email__c, Phone__c, contact__c
FROM Case_Contact__c WHERE Case__c = :Parent.Id];
exclude = new List<Id>();
for (Case_Contact__c cc : CaseContacts) {
if (cc.contact__c != Null) {
exclude.add(cc.contact__c);
}
}
system.debug(exclude);
}
public List<Case_Contact__c> getCaseContacts() {
return this.CaseContacts;
}
}
More information: The Case_Contact__c object is a custom junction object that allows me to associate more then 1 contact to a case. When the X is clicked, the associated Case Contact record should be deleted. When the + is clicked next to a contact, a new case contact record should be created.
I have verified this functionality. The only thing I cannot seem to get working is the output panel (container) to rerender.
Update:
Code snippet after applying Alex's suggestion:
<apex:column headerValue="">
<!--<apex:commandLink value="X" action="{!DeleteCaseContact}" style="color:red;text-decoration:none;"
rerender="container" immediate="true">
<apex:param assignTo="{!ToDo}" value="{!CaseContact.Id}" name="{!CaseContact.Id}"/>
</apex:commandLink>-->
<apex:outputText value="X" style="color:red"/>
<apex:actionSupport event="onclick" action="{!DeleteCaseContact}" rerender="container">
<apex:param assignTo="{!ToDo}" value="{!CaseContact.Id}" name="{!CaseContact.Id}"/>
</apex:actionSupport>
<apex:variable var="rowCount" value="{!rowCount + 1}"/>
</apex:column>
Unfortunately this did not work either. It was able to delete the case contact record as desired but the page did not update.
apex:pageMessages
and you may be masking/hiding any errors that occur when the action methods execute - this can be a common problem when rerendering isn't happening as expected; also, your + and x action methods should return null