You need to sign in to do that
Don't have an account?

CampaignMember.Status picklist not limited to the Campaign I'm on
I'm creating a UI for updating CampaignMember Statuses. I get all the members of a Campaign to a list and then bind that list of CampaignMembers to a dataTable. When the inputFields show up on the page, the Status picklist isn't limited to Statuses on my current campaign.
Seems to me that the picklist should be limited to available Status variables, just like it is in the UI.
Barring a change to that behavior, how is this for a plan of attack?
Thanks,
Steve
Here's the relevant controller code:
public List<CampaignMember> getMembers() {
allMembers.clear();
allMembers = [Select Contact.FirstName, Contact.LastName, Status from CampaignMember where CampaignId=:currentCampaignId];
return allMembers;
}
And the page code:
<apex:dataTable value="{!members}" var="member" id="theTable" rowClasses="odd,even" styleClass="tableClass" cellpadding="4"> <apex:column > <apex:facet name="header">Status</apex:facet> <apex:inputField value="{!member.Status}"/> </apex:column> . . .
Seems to me that the picklist should be limited to available Status variables, just like it is in the UI.
Barring a change to that behavior, how is this for a plan of attack?
- get my campaignmembers and bind them to a dataTable
- create a new SelectList in each row
- get items with a SOQL to CampaignMemberStatus, pulling only Statuses for this Campaign
- and when the user updates the campaign members, somehow get that selected value from each row and put it in member.status for each campaignmember
Thanks,
Steve
Do you use record types on the campaign to determine what statuses can be selected. If so I'm pretty sure Visualforce pages do not (yet?) support record types and all values for Status field will be shown.
Will your group of campaing members ever change? If not you can do this:
This way you don't execute the query everytime the get method is called.
Then on you page build your table as you normally would. The user would be able to select the status value and I believe this databinding will be automatic.
Then you could have a command button that saves and does a DML update on allMembers.
Campaign 1
a
b
c
Campaign 2
b
c
d
e
But when I look at the VF rendered picklist for CampaignMembers on Campaign 1, it shows:
a
b
c
d
e
d and e are invalid selections for Campaign 1, so I don't want them to show up in the picklist. I was hoping this would be standard functionality, but it appears to be a bug/feature.
Steve
To be honest I'm super familiar with all of the campaign relationships so maybe I'm overlooking something.
Edit: I just looked at the Schema and yup, Campaign member status is definitely special. You appear to be correct when you say this is a bug/feature.
Message Edited by TehNrd on 06-25-2008 04:23 PM
Steve
Page:
I'll give it a try and report back.
Steve
just run into the same problem - did you get some code to work for this?
PS - if you are writing a test script, I recommend putting it in the same class as the controller, as I seemed to get problems with the inner/outer issue if I created a separate test class.
Also, the only way I could find to actually deploy the custom controller was to create the new apex page as an empty shell in Production, with just the default 'hello world' text, upload this new custom controller class, and then go back and update the page code. Otherwise the deployment fails, because the test script can't find the page to test, but you can't create the actual page until the custom controller class is present - a slightly bizarre catch-22 me thinks...
It includes a test class as well... again, I am not sure how effective the actual test is, but acheives the level of coverage needed to deploy...
Page Code here:
so once you have more than about 25 members on a campaign, it quickly begins to exceed the governor limits...
In the end, I was able to bring the Status SOQL/ List Creation back up into the main class. I made some changes to reduce the SOQL/DML calls, but I haven't made it robust enough to handle unlimited campaigns. It would also be nice if you could only bring back a certain number of contacts at a time, and then use some previous - next construct to move through them, but that's for another time. Also - there is a change to the page, so remember to update that...
Page here - see line in red for changes
http://community.salesforce.com/sforce/board/message?board.id=Visualforce&thread.id=2034
For anyone who comes across this post, here is an updated version of the code that we found works better for something like Event Registration - instead of waiting for a user to click save, it saves the changed record and refreshes the screen.
Controller:
public class cmember2 { cMember [] members; public List<SelectOption> cmemberStatuses; //------------Method that gets the campaign members and populates the cMember class/container------------- public List<cMember> getMembers(){ if(members == null){ members = new cMember[]{}; for(CampaignMember [] cm: [Select Campaign.Name, Contact.Press__c, ContactId, Contact.FirstName, Contact.LastName,Contact.Account.Name, Contact.Email, Status from CampaignMember where HasResponded = FALSE AND CampaignId=:System.currentpagereference().getParameters().get('id')order by Contact.LastName asc]) { for (Integer i = 0, j = 0; i < cm.size(); i++) { system.debug('Adding to Members'); members.add( new cMember(cm[i]) ); } } } return members; } //-------------------Method to get the status picklist selections for the given campaign------------------- public List<SelectOption> getcMemberStatuses(){ List<SelectOption> options = new List<SelectOption>(); if(cmemberStatuses == null){ for(CampaignMemberStatus stat : [select ID, Label from CampaignMemberStatus where CampaignID = :System.currentpagereference().getParameters().get('id')]){ options.add(new SelectOption(stat.Label,stat.Label)); } } return options; } //----------Container for the campaign member and the picklist-------- public class cMember { CampaignMember cm; // public List<SelectOption> cMemberStatuses; public string cmStatus{get; set;} public cMember(CampaignMember cmb){ cm = cmb; cmStatus = cmb.Status; } public CampaignMember getCampaignMember(){ return cm; } } //-------Save or action method------------- public PageReference save(){ List<CampaignMember> CampaignMemberUpdate = new List<CampaignMember >(); system.debug('in save'); for(cMember mem: members){ If (mem.cm.Status != mem.cmStatus) { mem.cm.Status = mem.cmStatus; CampaignMemberUpdate.add(mem.cm); } } update CampaignMemberUpdate ; members = null; members = getMembers(); PageReference updatedcm = new PageReference('/apex/capcmupdate2?id=' + System.currentpagereference().getParameters().get('id') ); updatedcm.setRedirect(true); return updatedcm; } public PageReference cancel() { PageReference returntoPage = new PageReference('/' + System.currentpagereference().getParameters().get('id')); return returntoPage; } public static testMethod void cmember2() { Campaign newc = new Campaign(Name='Test One Campaign'); insert newc; system.debug('Created Campaign: ' + newc.Id); Contact[] newcon = new Contact[]{}; for (integer i=0;i<200;i++) { newcon.add(new Contact( LastName='TestL' + i, FirstName = 'TestF' )); } insert newcon; CampaignMember [] newcm = new CampaignMember []{}; for (integer i=0;i<200;i++) { newcm.add(new CampaignMember ( ContactId=newcon[i].Id, CampaignId=newc.Id )); } insert newcm; Test.startTest(); system.debug('Starting Test: DML Rows =' + Limits.getDMLRows()); PageReference pageRef = Page.capcmupdate2; Test.setCurrentPage(pageRef); // Add parameters to page URL ApexPages.currentPage().getParameters().put('id', newc.Id); system.debug(ApexPages.currentPage().getURL()); Test.setCurrentPage(pageRef); // Instantiate a new controller with all parameters in the page cmember2 cmember2 = new cmember2(); cmember2.getmembers(); //List <SelectOption> Status = cmember2.members[0].getcMemberStatuses(); List <SelectOption> Status = cmember2.getcMemberStatuses(); CampaignMember cm = cmember2.members[0].getCampaignMember(); cmember2.members[0].cmStatus = 'Responded'; cmember2.save(); String nextPage = cmember2.save().getUrl(); System.assertEquals(ApexPages.currentPage().getURL(), nextPage); CampaignMember[] checkcms = [select Id, Status from CampaignMember where CampaignId = :newc.Id and ContactId = :newcon[0].Id]; System.assertEquals('Responded', checkcms[0].Status); String nextPage1 = cmember2.cancel().getUrl(); System.assertEquals('/' + newc.Id, nextPage1); } }
Page:
<apex:page controller="cmember2"> <apex:form > <apex:pageBlock id="cmain" mode="edit"> <apex:commandButton action="{!cancel}" value="Return to Campaign" id="returnButton"/> <apex:pageBlockTable id="members" value="{!members}" var="member" cellPadding="4" border="0"> <apex:column > <apex:facet name="header">First Name</apex:facet> <apex:outputField value="{!member.CampaignMember.Contact.FirstName}"/> </apex:column> <apex:column > <apex:facet name="header">Last Name</apex:facet> <apex:commandLink rerender="detail">{!member.CampaignMember.Contact.LastName}<apex:param name="cid" value="{!member.CampaignMember.ContactId}"/></apex:commandLink></apex:column> <apex:column > <apex:facet name="header">Press</apex:facet> <apex:outputField value="{!member.CampaignMember.Contact.Press__c}"/> </apex:column> <apex:column > <apex:facet name="header">Organization</apex:facet> <apex:outputField value="{!member.CampaignMember.Contact.Account.Name}"/> </apex:column> <apex:column > <apex:facet name="header">Email</apex:facet> <apex:outputField value="{!member.CampaignMember.Contact.Email}"/> </apex:column> <apex:column > <apex:facet name="header">Current Status</apex:facet> <apex:outputField value="{!member.CampaignMember.Status}"> </apex:outputField> </apex:column> <apex:column > <apex:facet name="header">New Status</apex:facet> <apex:selectList size="1" value="{!member.cmStatus}" > <apex:actionSupport event="onchange" action="{!save}" rerender="member"/> <apex:actionSupport event="oncomplete"/> <apex:selectOptions value="{!cMemberStatuses}"/> </apex:selectList> </apex:column> </apex:pageBlockTable> <apex:outputPanel id="detail"><apex:detail subject="{!$CurrentPage.parameters.cid}" relatedList="true" title="false"/></apex:outputPanel> </apex:pageBlock> <apex:pageBlock id="cmainfooter" mode="edit"> </apex:pageBlock> </apex:form> </apex:page>