8

Background: I've been working on a dynamic contact search page modeled on Jeff Douglas 2010 post.

It works, and now I am exploring ways to add pagination and the ability to select records and take actions.

Was reading 'visualforce in practice' and on p62 they demonstrate how to use a standardSetController inside a custom controller to provide pagination and other functionality.

Question Started fresh using the standardSetController, and Pagination is working well, but I have not been able to figure out how to pass a selected list of records back to the controller so that I could add the selected records to a campaign.

I've basically copied the code from the book and just switched it up to work on contacts and added an apex:inputcheckbox field. It seems like the standard set controller methods getSelected / setSelected methods would allow me to do this, but I cant pass selected records back to the controller successfully.

I've seen some examples of using a wrapper class for this type of functionality, but want to confirm that its not possible to use the standardSetController methods before heading down that road.

Visualforce Page

<apex:page controller="CustomSearchListController">
    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockTable value="{!ssc.Records}" var="c" rows="25">
                <apex:column ><apex:inputCheckbox value="{!ssc.Selected}"/>     
                </apex:column>
                <apex:column value="{!c['firstname']}"/>
                <apex:column value="{!c['lastname']}"/>
            </apex:pageBlockTable>
            <apex:panelGrid columns="3">
                <apex:commandLink action="{!ssc.Previous}" value="previous page" rendered="{!ssc.HasPrevious}"/>
                <apex:commandLink action="{!ssc.Next}" value="Next Page" rendered="{!ssc.HasNext}"/>
                <apex:commandButton action="{!addToCampaign}" value="Add to campaign"/>
            </apex:panelGrid>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Controller

public with sharing class CustomSearchListController {

    public ApexPages.StandardSetController ssc {get; private set;}

  // init the controller and display some sample data when the page loads
  public CustomSearchListController() {
    ssc = new ApexPages.StandardSetController([SELECT firstname, lastname, account.name, Fellows_Status__c,id, account.id from contact LIMIT 1000]);
      }

    public list<contact> selContacts {get;set;}

    public pageReference addToCampaign(){
        system.debug('button clicked');
        list<campaignMember> cml = new list <campaignmember>();
        campaignmember cm = new campaignMember();
        selContacts = ssc.getSelected();
        system.debug('ssc' + ssc.getSelected());
        system.debug('selcontacts' + selContacts);
        FOR(contact c: selContacts){
            cm.ContactId = c.Id;
            cm.CampaignId = '70140000000XZt6AAG' ; //hard coding campaignID for testing purposes
            cml.add(cm);
        }
        insert cml;
        return null;
    }
  • 1
    I'm starting to think I should have posted a question like "Why is StandardSetController useless" instead of the one I did. Because it doesn't seem to "do" anything unless you're using it from a related list or mass edit button on a list view. – sfdcfox Mar 10 '16 at 21:35
  • @sfdcfox Yeah I am contemplating another question (different than this one) to try to understand why it is broken... – Adrian Larson Mar 10 '16 at 22:21
  • 2
    @AdrianLarson If you do so, please let me know, because I'll probably want in on that question. – sfdcfox Mar 10 '16 at 22:52
  • @sfdcfox what question are you referring to with 'instead of the one I did'? Can you point me at it? Sounds like the wrapper class is the right path? Strange that they feature the standardsetcontroller + custom controller in the book and on dev force if its only partially functional. – gorav Mar 12 '16 at 11:57
  • @adrianlarson if you do so please let me know as well. I'm assuming that the standard set controller option is a dead end given the commentary above but would love to understand more. – gorav Mar 26 '16 at 23:19
2

Weighing in with a not so nice but working workaround to use the standard set controller for the pagination yet have the ability to select records and pick these up within your controller without a wrapper class. (posting as an answer as i don't yet have the rep to comment below the question to suggest in a quick comment)

I created a Read Only checkbox field on the Contact object called SelectedInUI__c which was hidden from the layout and read only, its sole purpose being to give a selectable option on each SObject within the StandardSetController.getRecords() collection.

I then tied in this field to the VF page and controller given in your example.

VF Page

<apex:page controller="CustomSearchListController">
<apex:form >
    <apex:pageBlock >
        <apex:pageBlockTable value="{!ssc.Records}" var="c" rows="25">
            <apex:column >
                <apex:inputCheckbox value="{!c['SelectedInUI__c']}"/>
                <!--<apex:inputCheckbox value="{!ssc.Selected}"/>-->
            </apex:column>
            <apex:column value="{!c['firstname']}"/>
            <apex:column value="{!c['lastname']}"/>
        </apex:pageBlockTable>
        <apex:panelGrid columns="3">
            <apex:commandLink action="{!ssc.Previous}" value="previous page" rendered="{!ssc.HasPrevious}"/>
            <apex:commandLink action="{!ssc.Next}" value="Next Page" rendered="{!ssc.HasNext}"/>
            <apex:commandButton action="{!addToCampaign}" value="Add to campaign"/>
        </apex:panelGrid>
    </apex:pageBlock>
</apex:form>

Controller

public with sharing class CustomSearchListController {

    public ApexPages.StandardSetController ssc {get; set;}

    // init the controller and display some sample data when the page loads
    public CustomSearchListController() {
        ssc = new ApexPages.StandardSetController([SELECT firstname, lastname, account.name, id, account.id, SelectedInUI__c from contact LIMIT 1000]);
        for(SObject contact : ssc.getRecords())
        {
            /*
            *    Within the context of the controller set the Boolean field for all records to false
            *    if no updates to the Contact record are occuring setting the local context should be okay. 
            */
            contact.put('SelectedInUI__c', false);
        }
    }

    public list<contact> selContacts {get;set;}

    public pageReference addToCampaign()
    {
        list<campaignMember> cml = new list <campaignmember>();

        for(SObject contact : ssc.getRecords())
        {
            /*
            *    As all values earlier in the controller were set to false, only user selected records will meet the following criteria.
            */
            if((Boolean)contact.get('SelectedInUI__c'))
            {
                campaignmember cm = new campaignMember();
                cm.ContactId = contact.Id;
                cm.CampaignId = '70158000000KIXI' ; //hard coding campaignID for testing purposes
                cml.add(cm);
            }
        }
        insert cml;
        return null;
    }
}

As i said, its not the nicest solution but it allows you to use the pagination from the StandardSetController with the line by line selection ability desired.

|improve this answer|||||
  • Looks like a workable approach. Will give it a shot and report back – gorav May 21 '16 at 23:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.