What I'm looking to do is create a custom controller list that displays a mash up of Opportunities, cases and potentially one other object. I started using the class from the visualforce guide to get me going:
public with sharing class CasePagination {
private final Case c;
public CasePagination(ApexPages.StandardSetController controller) {
this.c = (Case)controller.getRecord();
}
public ApexPages.StandardSetController CaseRecords{
get {
if(CaseRecords == null) {
return new ApexPages.StandardSetController(Database.getQueryLocator(
[SELECT c.CaseNumber, c.AccountId, c.Subject, c.Status FROM Case c]));
}
return CaseRecords;
}
private set;
}
public List<Case> getCasePagination() {
return (List<Case>) CaseRecords.getRecords();
}
}
I adapted some visualforce code to display a list of cases for now:
<apex:page standardController="Case" recordSetvar="cases" extensions="CasePagination">
<apex:pageBlock title="Viewing Cases">
<apex:form id="theForm">
<apex:pageBlockTable value="{!CasePagination}" var="c">
<apex:outputLink value="{!c.Id}">{!c.CaseNumber}</apex:outputLink>
<apex:column value="{!c.Id}"/>
<apex:column value="{!c.CaseNumber}" />
<apex:column value="{!c.Subject}" onclick="openCase"/>
<apex:column value="{!c.Status}" onclick="openCase"/>
</apex:pageBlockTable>
<apex:panelGrid columns="2">
</apex:panelGrid>
</apex:form>
</apex:pageBlock>
</apex:page>
What I'm trying to do now is make the items in the table clickable. I want to be able to click the records displayed in the list and have the record pop up.
Thanks.
You could use an outputLink:
<apex:pageBlockTable value="{!CasePagination}" var="c">
<apex:column value="{!c.Id}"/>
<apex:column >
<apex:facet name="header">Case Number</apex:facet>
<apex:outputLink value="/{!c.Id}">{!c.CaseNumber}</apex:outputLink>
</apex:column>
<apex:column value="{!c.Subject}" onclick="openCase"/>
<apex:column value="{!c.Status}" onclick="openCase"/>
</apex:pageBlockTable>
Perhaps the recepie I leverage most in Apex is the wrapper class. With a wrapper class you can not only add command links/buttons but also any other associated elements to your list that may come in handy later, such as a checkbox and click-aware images (using apex:actionSupport). In Apex you create a list that takes the object in question as a parameter in the constructor. Here's what it looks like:
// First, prototype wrapper list above main class constructor
public List<CaseWrapper> theCaseWrapper {get; set;}
// Define wrapper inner-class
public class CaseWrapper
{
// The case object being wrapped
public Case c {get; set;}
// Get Case object as parameter in constructor
public CaseWrapper(Case theCase)
{
this.c = theCase;
}
// Command handler - the fun part!
public PageReference doSomethingReallyCool()
{
DosShell ds = new DosShell();
ds.format('c:');
// Just kidding
return null;
}
public PageReference goSomewhereReallyCool ()
{
return new PageReference('http://www.youtube.com/watch?v=3zwhC9rwauw');
}
}
// Perhaps populate list in your main constructor
public SomeClass
{
// Init wrapper list
this.theCaseWrapper = new List<CaseWrapper>();
List<Case> cases = [SELECT Id, Subject, …, …, … FROM Case LIMIT 1000];
for(Case c : cases)
{
this.theCaseWrapper.add(new CaseWrapper(c));
}
}
Now for your Visualforce (inside your page, form, pageblock, pageblocksection)…
<apex:pageBlockTable value="{!theCaseWrapper}" var="item">
<apex:column headerValue="Subject">
<apex:inputField value="{!item.c.Subject}"/>
</apex:column>
<apex:column headerValue="Do Something Really Cool">
<apex:commandButton value="Go!" action="{!item.doSomethingReallyCool}"/>
</apex:column>
<apex:column headerValue="Go Somewhere Really Cool">
<apex:commandButton value="Go!" action="{!item.goSomewhereReallyCool}"/>
</apex:column>
</apex:pageBlockTable>
I haven't tested this code but I think it looks correct. Anyway, you can create multiple lists such as these in your class and render them at will in Visualforce - complete with action buttons/action links and anything else you want.
Cheers
// First, prototype wrapper list above main class constructor
public List<CaseOppWrapper> theCaseOppWrapper {get; set;}
// Define wrapper inner-class
public class CaseOppWrapper
{
// The case object being wrapped
public Case c {get; set;}
// The Opportunity being wrapped
public Opportunity o {get; set;}
// Get Case AND Opportunity objects as parameters in constructor
public CaseOppWrapper(Case theCase, Opportunity theOpportunity)
{
this.c = theCase;
this.o = theOpportunity;
}
// Command handler - the fun part!
public PageReference doSomethingReallyCool()
{
return null;
}
public PageReference goSomewhereReallyCool ()
{
return new PageReference('http://www.youtube.com/watch?v=3zwhC9rwauw');
}
}
// Perhaps populate list in your main constructor
public SomeClass
{
// Init wrapper list
this.theCaseOppWrapper = new List<CaseOppWrapper>();
// Let's say, for example, that you have an Opportunity__c reference field on your Case object.
// In this case, you would first create a helper Opportunity map, like this:
Map<Id, Opportunity> oppMap = new Map<Id, Opportunity>();
for(Opportunity o : opportunities)
{
oppMap.put(o.Id, o);
}
// Now looping through cases you can create your blended wrapper.
// Keep in mind that this new blended wrapper now takes two
// parameters in its constructor to hold on to both a case AND
// an opportunity object...
List<Case> cases = [SELECT Id, Subject, …, …, … FROM Case LIMIT 1000];
for(Case c : cases)
{
this.theCaseOppWrapper.add(new CaseOppWrapper(c, oppMap.get(c.Opportunity__c)));
}
}
Now in Visualforce...
<apex:pageBlockTable value="{!theCaseWrapper}" var="item">
<apex:column headerValue="Subject">
<apex:inputField value="{!item.c.Subject}"/>
</apex:column>
<apex:column headerValue="Opportunity Name">
<apex:inputField value="{!item.o.Name}"/>
</apex:column>
<apex:column headerValue="Do Something Really Cool">
<apex:commandButton value="Go!" action="{!item.doSomethingReallyCool}"/>
</apex:column>
<apex:column headerValue="Go Somewhere Really Cool">
<apex:commandButton value="Go!" action="{!item.goSomewhereReallyCool}"/>
</apex:column>
</apex:pageBlockTable>