function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Squire KershnerSquire Kershner 

Add "Add to Campaign" button to visualforce related list

I was asked to add a filtered related list to Contact, and accomplished this with visualforce.  I created a visualforce element that limits the campaign history, added it to the layout, and then removed the orignal Campaign History related list.  However, the request also asks that the new element now have the orignal "add to campaign" button on it.  However, I've tried multiple ways of getting the button transferred to the new element with poor results.

The best effort was using the following:
<apex:commandButton value="Campaign Member Assignment" action="{!URLFOR($Action.Contact.AddToCampaign,Contact.Id)}"/>

It opens the Campaign Member page inside the Visualforce element (bad) and doesn't actually save the member (also bad).
Help?

 
ShashankShashank (Salesforce Developers) 
I tried with this code:

<apex:page standardController="contact">
  <apex:form >
  <apex:commandButton value="Campaign Member Assignment" action="{!URLFOR($Action.Contact.AddToCampaign,Contact.Id)}"/>
  </apex:form>
</apex:page>

It went to the campaign member page aand it did add the contact to the campaign.

Would you be able to elaborate a little more on the exact behavior you are seeing and detailed replication steps?
Squire KershnerSquire Kershner
So this is the same code I used, however:
1)  The button opens the Campaign Add Members page inside the visualforce element.
2)  It doesn't first open the Lookup (like the standard button does)
3)  If you click the magnifiying glass to find a Campaign, and then select the [Add to Campaign] button, the resulting page states
"0 new members have been added to the campaign "Demo Campaign" with a Status of "Sent"."
And the contact is not actually added to the campaign.

Are you saying you are able to successfully add the contact per standard functionalty?
Squire KershnerSquire Kershner
Here's my Visualforce code
 
<apex:page standardController="Contact" extensions="CampaignHistoryExtension">
    <apex:form >
        <apex:commandButton value="Campaign Member Assignment" action="{!URLFOR($Action.Contact.AddToCampaign,Contact.Id)}"/>
        <apex:pageBlock >
            <apex:outputLink target="_new" value="/701?rlid=RelatedCampaignList&id={!contact.id}">
                <p>Show All Campaigns</p>
            </apex:outputLink>
               
            <apex:pageBlocktable value="{!campaignMemberRecords}" var="member" rows="5" >
                <apex:column value="{!member.campaign.name}" HeaderValue="Campaign Name"/>
                <apex:column value="{!member.campaign.startdate}" HeaderValue="Campaign Start Date"/>
                <apex:column value="{!member.campaign.type}" HeaderValue="Campaign Type"/>
                <apex:column value="{!member.status}" HeaderValue="Member Status"/>
                <apex:column value="{!member.lastmodifieddate}" HeaderValue="Member Status Last Update"/>
                </apex:pageBlocktable>


        </apex:pageBlock>
    </apex:form>
</apex:page>

And here's the extension
 
//VF extension, designed to extend the Contact standard controller to display a filtered campaign history list
public class CampaignHistoryExtension {

//this is the Contact ID variable passed by the standard controller
    private ID thisContactID;
    
//List variable of campaign member records to return to the page as the sorted campaign list
    private transient List<campaignMember> campaignMemberRecords;
    
//Constructor to extend the standard Contact controller a\@param controller
//@param the standardController object constructed by specifying the standardControler attribute in an apex:page
    public CampaignHistoryExtension(ApexPages.StandardController controller) {
        thisContactID = controller.getId();
        refreshCampaignMemberRecords();
    }
    
//@return the list of Campaign Member records to present as the campaign history
    public LIST <CampaignMember> getCampaignMemberRecords(){
        return campaignMemberRecords;
    }    
    
//refresh the list of campaign member records presented as teh contact campaign history by qurying the db using known properties as filter
    private void refreshCampaignMemberRecords(){
        campaignMemberRecords = [
            SELECT ID, CampaignID, Campaign.Name, Campaign.StartDate, ContactID, Contact.Name, Status, 
                Campaign.Type, campaign.Parent_Campaign__c, LastModifiedDate
            FROM CampaignMember
            WHERE ContactID = :thisContactID
            AND Campaign.Parent_Campaign__c=TRUE
            ORDER BY Campaign.StartDate DESC];
    }
}

 
ShashankShashank (Salesforce Developers) 
Surprisingly, I am able to replicate the issue as you stated. I must have missed out something. Turns out, the "AddToCampaign" action that we have available is not the button that you see on the campaign history related list, but the list view button that you see on the Contacts tab list views. Both are not the same.
Marty C.Marty C.
Hello, Squire, I don't think there's a great way to achieve what you're trying to do in this case. You could try the code below as a workaround, but I don't think there's a realy good way to replicate the standard Add to Campaign button.

 
<apex:page standardController="Contact" extensions="CampaignHistoryExtension">
    <!-- Note the use of method="post" and also the $ObjectType.Contact merge
         variable. Also, the other required form parameter is ids. -->
    <form method="post" action="{!URLFOR($Action.Contact.AddToCampaign, $ObjectType.Contact)}">
        <input type="hidden" name="ids" value="{!Contact.Id}"/>
        <input type="submit" value="Campaign Member Assignment"/>
    </form>
    
    <apex:form >
        <!-- Replaced the apex:commandButton with the custom HTML form above
        <apex:commandButton value="Campaign Member Assignment" action="{!URLFOR($Action.Contact.AddToCampaign,Contact.Id)}"/>
        -->
        <apex:pageBlock >
            <apex:outputLink target="_new" value="/701?rlid=RelatedCampaignList&id={!contact.id}">
                <p>Show All Campaigns</p>
            </apex:outputLink>
               
            <apex:pageBlocktable value="{!campaignMemberRecords}" var="member" rows="5" >
                <apex:column value="{!member.campaign.name}" HeaderValue="Campaign Name"/>
                <apex:column value="{!member.campaign.startdate}" HeaderValue="Campaign Start Date"/>
                <apex:column value="{!member.campaign.type}" HeaderValue="Campaign Type"/>
                <apex:column value="{!member.status}" HeaderValue="Member Status"/>
                <apex:column value="{!member.lastmodifieddate}" HeaderValue="Member Status Last Update"/>
                </apex:pageBlocktable>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Basically you're creating a custom HTML form that uses the dynamic URL generated by $Action.Contact.AddToCampaign as the action. Furthermore, the form must use HTTP POST (i.e., method="post").