I've written a Visualforce page and controller intended to override both the New and Edit buttons for the standard Case object.
I have an inputField for an Account lookup enclosing an actionSupport component. The action displaySessions()
recomputes a list of objects of a custom Apex wrapper class that each have lookups to the same Account object, then rerenders a pageBlockSection on the New/Edit page of the properties of those objects.
The below code works perfectly fine when overriding a typical edit page. In testing, this usually looked like
cs53.salesforce.com/apex/editcase?id=5000j000001k27U
In practice when overriding, SF throws in some extra params, but the functionality works either way:
However, when creating a case from scratch by clicking an overridden New button, the functionality does not work. The page loads the initial pageBlockTable (logic in controller code below omitted) but rerender does not occur. I included a debug statement in the displaySessions()
code that that the vfp action=
should call (see below code), and while the debug statement appears when the id param is passed in, it doesn't in the New Case scenario, where the id param is missing:
Same behavior whether I use the inbuilt record type select UI or override/skip it. Adding &id=5000j000001k27U
to the above and reloading causes expected behavior to return.
This all leads me to believe that not setting the controller extension constructor on load is preventing inputField actionSupport from firing, but at a loss for how to change this.
Any help much appreciated. Code snippets below:
VFP
<apex:inputField value="{!Case.AccountId}" required="true" rendered="{!ISBLANK($CurrentPage.parameters.fromAcc)}">
<apex:actionSupport action="{!displaySessions}" event="onchange" rerender="session_block" >
</apex:actionSupport>
</apex:inputField>
...
<apex:pageBlockSection title="Session Association" columns="1" collapsible="true" id="session_block">
<apex:outputPanel rendered="{!IF(AND(OR(ISBLANK(sessions), sessions.size < 1), ISBLANK($CurrentPage.parameters.fromAcc), case.AccountId == null), true, false)}" style="display:block; width:100%; border: 1px solid #e0e3e5; padding:4px; margin-bottom:-10px;">
No records to display.
</apex:outputPanel>
<apex:outputPanel rendered="{!IF(AND(OR(ISBLANK(sessions), sessions.size < 1), ISBLANK($CurrentPage.parameters.fromAcc), case.AccountId != null), true, false)}" style="display:block; width:100%; border: 1px solid #e0e3e5; padding:4px; margin-bottom:-10px;" >
No sessions for selected account. A new open session will be automatically created with case.
</apex:outputPanel>
<apex:outputText label="Currently Selected Session" value="{!Case.Session__r.Name}" rendered="{!IF(AND(NOT(ISBLANK(sessions)), sessions.size > 0, ISBLANK($CurrentPage.parameters.fromAcc), NOT(newSessionCreated = true)), true, false)}" />
<apex:commandButton value="New Session" action="{!newSession}" style="margin-left:18%;" rerender="session_block" rendered="{!AND(ISBLANK($CurrentPage.parameters.fromAcc), NOT(newSessionCreated = true), AND(sessions != null, sessions.size > 0))}"/>
<apex:pageBlockTable id="sessions" value="{!sessions}" var="s" rendered="{!IF(AND(NOT(ISBLANK(sessions)), sessions.size > 0, ISBLANK($CurrentPage.parameters.fromAcc), NOT(newSessionCreated = true)), true, false)}">
<apex:column headerValue="Select" >
<apex:actionsupport event="onclick" rerender="">
<input type="radio" name="selectRadio" value="Case.selectedSessionId"/>
<apex:param name="sessid" value="{!s.s.id}" assignTo="{!selectedSessionId}">
</apex:param>
</apex:actionsupport>
</apex:column>
<apex:column headerValue="Session">
<apex:outputLink value="{! '/' & s.s.id}">{!s.s.Name}</apex:outputLink>
</apex:column>
<apex:column width="90%" >
<apex:pageblocktable value="{!s.cases}" var="c" width="100%" rendered="{!IF(s.cases.Size = 0, false, true)}" id="PleaseHideMe">
<apex:column headerValue="Case" width="6%">
<apex:outputLink value="{!URLFOR($Action.Case.View, c.id)}">{!c.CaseNumber}</apex:outputLink>
</apex:column>
<apex:column headerValue="Subject" value="{!c.Subject}" width="15%"/>
<apex:column headerValue="Category" value="{!c.Category__c}" width="12%"/>
<apex:column headerValue="Date Opened" value="{!c.CreatedDate}" width="10%"/>
<apex:column headerValue="Status" value="{!c.Status}" width="11%"/>
<apex:column headerValue="Owner" value="{!c.Owner.Name}" width="15%"/>
</apex:pageblocktable>
</apex:column>
</apex:pageBlockTable>
<apex:outputText label="Session" value="{!singleSession.Name}" rendered="{!$CurrentPage.parameters.fromAcc = 'true'}" />
<apex:outputText label="Session" value="{!singleSession.Name}" rendered="{!newSessionCreated = true}" />
<apex:commandButton value="Undo" action="{!undoNewSession}" style="margin-top:5px;margin-bottom:-5px; margin-left:18%;" rendered="{!newSessionCreated = true}" rerender="session_block" />
</apex:pageBlockSection>
Controller
public Case cas {get; set;}
public EditCaseController(ApexPages.StandardController controller) {
...
// set Case to existing case if in Edit mode, create new case otherwise
cId = ApexPages.currentPage().getParameters().get('id');
if(cId != null && cId != '') {
cas = (Case) stdCtrl.getRecord();
} else {
cas = new Case();
}
...
}
public void displaySessions() {
System.Debug('DISPLAYSESSIONS RAN');
newAccId = cas.AccountId;
if (newAccId != null) {
acc = [Select Id from Account where Id =: newAccId limit 1];
sessionObjs = [Select Id, Name, Account__c, Start_Time__c, End_Time__c
from Session__c where Account__c =:acc.Id order by Name Desc];
createSessionWrapper(sessionObjs);
}
}
Correct behavior when id in URL:
Incorrect behavior when id is missing from URL:
EDIT Code I tried so far using apex:actionFunction in place of Support:
<apex:inputField value="{!Case.AccountId}" rendered="{!ISBLANK($CurrentPage.parameters.fromAcc)}" onchange="rerenderSessions">
<apex:actionFunction action="{!displaySessions}" name="rerenderSessions" rerender="session_block" >
</apex:actionFunction>
</apex:inputField>`
EDIT 2 Got it to work by grabbing the record again in displaySessions() while using an actionRegion (needs to use this hierarchy to display correctly) and most importantly, by calling getRecord in the controller action method:
VFP
<apex:pageBlockSectionItem id="AccountSelectionItem">
<apex:outputLabel value="Account Name" for="accountfield" />
<apex:actionRegion >
<apex:inputField value="{!Case.AccountId}" label="Account" required="true" id="accountfield">
<apex:actionSupport event="onchange" action="{!displaySessions}" rerender="session_block" />
</apex:inputField>
</apex:actionRegion>
</apex:pageBlockSectionItem>
Controller
public void displaySessions() {
System.Debug('DISPLAYSESSIONS RAN');
System.Debug('NEWACCID: ' + newAccId);
cas = (Case) stdCtrl.getRecord();
newAccId = cas.AccountId;
System.Debug('CAS.ACCID: ' + cas.AccountID);
if (newAccId != null) {
acc = [Select Id from Account where Id =: newAccId limit 1];
sessionObjs = [Select Id, Name, Account__c, Start_Time__c, End_Time__c
from Session__c where Account__c =:acc.Id order by Name Desc];
createSessionWrapper(sessionObjs);
}
}