Leverage StandardSetController in Apex and Visualforce

Preview:

DESCRIPTION

 

Citation preview

Leverage StandardSetController in Apex and Visualforce Developer Track 2012

Nebojsa (Nash) Zgonjanin, CRM Developer

OnPath Ottawa, Ontario, Canada (www.onpath.com)

Nebojsa.zgonjanin@onpath.com

@Nzgon

ca.linkedin.com/in/nashzgonjanin

Abstract

• Do you use list view filters?

• Would you like to use that same logic in your Visualforce

pages?

• Don’t reinvent the wheel

• Save time, and make your admin happier as well

Nebojsa (Nash) Zgonjanin CRM Developer

• Salesforce MVP (winter 2012),

• Salesforce developer more than 6 years,

• Senior developer (MS .NET) more than

15 years,

• Work for www.OnPath.com, Ottawa,

Ontario, Canada

Session Objectives

• StandardSetController and List View Filter Criteria (logic)

• jQuery Table Sort and Visualforce page

• Hierarchy Custom Setting used to control functionality per

org (profile or user level)

• Demo ”Add to Campaigns” of implemented technology

Session Objectives

• Short live demo of application to

familiarize audience with topic

• Use of Eclipse to browse code

and point to key moments

• Code in PPT presentation is used

as reference

Solution Intro I

• StandardSetController and List View Filter Criteria

• Define StandardSetController (SOQL query)

• Apply Filter Criteria from List View to StandardSetController

• Execute SOQL and use in Apex code

Solution Intro II

jQuery Table Sort and Visualforce Page

• jQuery Setting

• Static resources

• <apex:includeScript>

• Mash up of:

• standard HTML table tags

• <apex:repeat> tag

• jQuery <script> code

Solution Intro III

Hierarchy Custom Settings (Levels of use)

• Org default

• Profile (group of users)

• User (individual)

• Use of setting values in Apex code

• Use of setting values in Visual Force page

• Demo: User (Serbian) vs. Org Default (English)

Nash

Code sample (package) available here:

https://github.com/nzgonjanin/Dreamforce2012

Thank You

Nebojsa (Nash) Zgonjanin, CRM Developer

OnPath Ottawa, Ontario, Canada (www.onpath.com)

Nebojsa.zgonjanin@onpath.com

@Nzgon

ca.linkedin.com/in/nashzgonjanin

Solution intro I always wanted to leverage platform functionality and add more of client side functionality that browser bring in game. Combination of APEX controller extension and standard controllers (ApexPages.StandardController and ApexPages.StandardSetController) give me option to leverage standard platform functionality and add more flexibility and user interface functionality to Visual Force page using jQuery Table sorter (jquery.tablesorter.min.js) add on, that enable sorting of multiple columns. Using Custom setting I made available different set of parameters to be used per Org; Profile or User (labels, list views for filtering, Error Messages…) that enable easy internationalization if needed.

Objectives and Solution I What is the Add to Campaigns app

Salesforce.com provides features for adding many people to a single campaign, but what about an organization that manages multiple, ongoing campaigns like newsletters, customer programs, annual events, and even holiday card lists?

Manually adding a single person to multiple campaigns one by one is a pain, and contributes to poor adoption, and incomplete or unusable data.

This app application in salesforce.com allows users to add a single contact or lead to multiple campaigns with as few clicks as possible.

Objectives and Solution II There are two portions to this application: end-user and administrator (non-developer).

NOTE: Custom Settings, Standard List View filter, Standard Controller, StandardSetController are used to give end user (administrator) flexibility to manage data set used for app in combination with visual force page ADDTOCAMPAIGNS_LISTVIEWFILTER or using standard List View management under Campaigns tab. The end-user portion of the application works the same for both contacts and leads. Add a custom button to the Campaign History related list for both Leads and Contacts called "Add to Campaigns". When the end-user clicks this button display a list of campaigns with check boxes and a "check all" option. (The query for the list of campaigns will be determined in the administrator portion of the application.) When the end-user submits the form, insert the contact/lead to the campaign as member with the default status for that campaign and return the user back to the standard contact/lead details page.

APEX controller extension (addtocampaigns_Extension.cls I )

public with sharing class addtocampaigns_Extension { //variables used on Visual force page for interaction with end user public Lead ParticipantLead {get; set;} //Lead record returned based on Id (pid) query parameter from custom button public Contact ParticipantContact {get; set;} //Contact record returned based on Id (pid) query parameter from custom button public string ParticipantId {get;set;} //Value of Query parameter pid public list<addtocampaigns_Wrapper> Campaign_List=new list<addtocampaigns_Wrapper>(); //List of campaign records to be used for selection public Boolean SubmitDisabled {get;set;} //[Submit] button and [Select All] button can be used just ones public AddtoCampaignsSetting__c mySetting {get; set;} //Custom Setting for logged user public addtocampaigns_Extension(ApexPages.StandardController controller) { //Standard controller extensin used to add custom functionality to visual force page ParticipantId=System.currentPageReference().getParameters().get('pid'); mySetting=AddtoCampaignsSetting__c.getInstance();//Custom Setting Definitions getParticipant(); //get Participant data from Lead or Contact getCampaign_List();//get list for campaign selection }

APEX controller extension (addtocampaigns_Extension.cls II)

public ApexPages.StandardSetController con { //Standard Set controller used to add custom functionality to visual force page //and leverage standard behavior of List View filters get { if(con == null) { //Standard set controller query used to retrieve data from Campaign object //used on visual force page to select potential campaigns integer myLimit=integer.valueOf(mySetting.RecordSet_Limit__c); if (myLimit==null){ myLimit=200; } con = new ApexPages.StandardSetController(Database.getQueryLocator( [Select Id, Name, StartDate,EndDate, Type, Status, ParentId, RecordTypeId FROM Campaign order By Name,StartDate limit :myLimit])); //in order to use it again you need to refresh page or go back to participant and start again //set filter id that is applied for Hierarchy setting Org/Profile/User if (mySetting.ListViewId__c!=null){

//Filter Magic is heppening here con.setPageSize(myLimit); con.setFilterID(mySetting.ListViewId__c); } } return con; } set; }

APEX controller extension (addtocampaigns_Extension.cls III)

//Queried data set is used to laverage data set public List<addtocampaigns_Wrapper> getCampaign_List() { //get list for campaign selection if (Campaign_List.Size()==0){ //Load campign list just ones on first page load //(List<Campaign>)con.getRecords()) will execute query and //apply defined mySetting.ListViewId__c as filter to set of records for (Campaign camp: (List<Campaign>)con.getRecords()){ Campaign_List.add(new addtocampaigns_Wrapper(camp)); //check if participant is already part of campaign and disable it for selection if (ParticipantId.startsWith('00Q')){ //process lead campaign member records for (CampaignMember CM :ParticipantLead.CampaignMembers){ if (CM.CampaignId==camp.Id && Campaign_List.Size()>0){ //disable check box on visual force page Campaign_List[Campaign_List.size()-1].disabled=true; break; } } }else{ //process contact campaign member records for (CampaignMember CM :ParticipantContact.CampaignMembers){ if (CM.CampaignId==camp.Id && Campaign_List.Size()>0){ //disable check box on visual force page Campaign_List[Campaign_List.size()-1].disabled=true; break; } } } } } return Campaign_List; }

Addtocampaigns_Wrapper.cls (used in APEX controller extension to support app functionality)

public with sharing class addtocampaigns_Wrapper { //variables used for creating add to Campaigns record public String message{ get; set; } //success message public Boolean checked{ get; set; } //check box for selection public Boolean disabled {get; set;} //if member is alread part of campaign selection check box is disabled public Campaign camp { get; set;} //Campaign record returned as part of data set driven by listView filter public addtocampaigns_Wrapper(){ //constructor without passed parameters camp = new Campaign(); checked = false; disabled = false; message=''; } public addtocampaigns_Wrapper(Campaign c){ //constructor with passed parameters camp = c; checked = false; disabled = false; message=''; } }//end of class

Visual Force Page code overview (addtocampaigns_ListViewFilter.page)

<apex:page standardController="Campaign"

tabStyle="Campaign" standardStylesheets="true">

<apex:sectionHeader title="Cloudspokes" subtitle="{!$Setup.AddtoCampaignsSetting__c.Header_Subtitle__c}"/>

<apex:enhancedList height="300" rowsPerPage="100" listId="{!$Setup.AddtoCampaignsSetting__c.ListViewId__c}" id="CampaignsList" customizable="True" />

</apex:page>

Visual Force Page code overview (addtocampaigns.page I)

<apex:page standardController="Campaign" extensions="addtocampaigns_Extension" tabStyle="Campaign" standardStylesheets="true"> <!-- jQuery plug in for table sort my multiple columns --> <apex:includeScript value="{!URLFOR($Resource.jQuery_TableSort, 'jquery-latest.js')}" /> <apex:includeScript value="{!URLFOR($Resource.jQuery_TableSort, 'jquery.tablesorter.min.js')}" /> <apex:stylesheet value="{!URLFOR($Resource.jQuery_TableSort , '/themes/blue/style.css')}" /> <script> $j = jQuery.noConflict(); $j(document).ready(function() { $j("#myTable").tablesorter( {sortList: [[1,0], [2,1]]} ); } ); </script> <apex:sectionHeader title="Cloudspokes" subtitle="{!$Setup.AddtoCampaignsSetting__c.Header_Subtitle__c}"/> <apex:form >

<apex:pageBlock id="CampaignMember" mode="detail"> <apex:pageBlockButtons > <apex:commandButton id="Back" action="{!GoToParticipant}“ value="{!$Setup.AddtoCampaignsSetting__c.button_Back_Label__c}" /> <apex:commandButton id="SelectAll" action="{!SelectAll}" value="{!$Setup.AddtoCampaignsSetting__c.button_SelectAll_Label__c}" disabled="{!SubmitDisabled}"/> <apex:commandButton id="Submit" action="{!Submit}" value="{!$Setup.AddtoCampaignsSetting__c.button_Submit_Label__c}" styleClass="btnImportant" disabled="{!SubmitDisabled}"/> <apex:commandLink id="FilterSetting" action="{!FilterSetting}" target="_blank" value="Filter Settings" /> </apex:pageBlockButtons>

Visual Force Page code overview (addtocampaigns.page II)

//Lead Section <apex:pageBlockSection title="{!$Setup.AddtoCampaignsSetting__c.pageBlockSection_Lead__c}" columns="2" showHeader="true" collapsible="false" rendered="{!if(ParticipantLead.Id==null,false,true)}"> <apex:outputField id="LeadFirstName" value="{!ParticipantLead.FirstName}" /> <apex:outputField id="LeadCompany" value="{!ParticipantLead.Company}" /> <apex:outputField id="LeadLastName" value="{!ParticipantLead.LastName}" /> <apex:outputField id="LeadEmail" value="{!ParticipantLead.Email}" /> </apex:pageBlockSection> //Contact section <apex:pageBlockSection title="{!$Setup.AddtoCampaignsSetting__c.pageBlockSection_Contact__c}" columns="2" showHeader="true" collapsible="false“ rendered="{!if(ParticipantContact.Id==null,false,true)}"> <apex:outputField id="ContactFirstName" value="{!ParticipantContact.FirstName}" /> <apex:outputField id="ContactCompany" value="{!ParticipantContact.Account.Name}" /> <apex:outputField id="ContactLastName" value="{!ParticipantContact.LastName}" /> <apex:outputField id="ContactEmail" value="{!ParticipantContact.Email}" /> </apex:pageBlockSection> //Select campaigns section that mix jQuery (client side) and APEX server side functionality <apex:pageBlockSection title="{!$Setup.AddtoCampaignsSetting__c.pageBlockSection_Campaigns__c}" columns="1" showHeader="true" > {!$Setup.AddtoCampaignsSetting__c.Note__c} </apex:pageBlockSection>

Visual Force Page code overview (addtocampaigns.page III)

//standard HTML table tags used with apex:repeat tag to obtain data set

<table id="myTable" class="tablesorter">

<thead> //table headers

<tr>

<th>{!$Setup.AddtoCampaignsSetting__c.column_Select_Header__c}</th>

<th>{!$Setup.AddtoCampaignsSetting__c.column_Name_Header__c}</th>

<th>{!$Setup.AddtoCampaignsSetting__c.column_StartDate_Header__c}</th>

<th>{!$Setup.AddtoCampaignsSetting__c.column_EndDate_Header__c}</th>

<th>{!$Setup.AddtoCampaignsSetting__c.column_Type_Header__c}</th>

<th>{!$Setup.AddtoCampaignsSetting__c.column_Status_Header__c}</th>

<th>Parent</th>

<th>Record Type</th>

</tr>

</thead>

<tbody> //table rows (data set from list view)

<apex:repeat value="{!Campaign_List}" var="Camp" id="theRepeat">

<tr>

<td> <apex:inputCheckbox id="Selected" value="{!Camp.checked}" disabled="{!Camp.disabled}"/></td>

<td> <apex:outputField id="Name" value="{!Camp.Camp.Name}"/></td>

<td> <apex:outputField id="StartDate" value="{!Camp.Camp.StartDate}"/></td>

<td> <apex:outputField id="EndDate" value="{!Camp.Camp.EndDate}"/></td>

<td> <apex:outputField id="Type" value="{!Camp.Camp.Type}"/></td>

<td><apex:outputField id="Status" value="{!Camp.Camp.Status}"/></td>

<td><apex:outputField id="Parent" value="{!Camp.Camp.ParentId}"/></td>

<td><apex:outputField id="RecordType" value="{!Camp.Camp.RecordTypeId}"/></td>

</tr>

</apex:repeat>

Custom Setting Hierarchy type overview Hierarchy Custom Settings: A type of custom setting that uses a built-in hierarchical logic that lets you “personalize” settings for specific profiles or users. The hierarchy logic checks the organization, profile, and user settings for the current user and returns the most specific, or “lowest,” value. In the hierarchy, settings for an organization are overridden by profile settings, which, in turn, are overridden by user settings.

https://na14.salesforce.com/help/doc/user_ed.jsp?loc=help&target=cs_manage_data.htm&section=integrate

Recommended