3

I have a requirement for which I've written some code for paginated wrapped records with checkboxes using standardsetcontroller. Now I want to display all paginated records with page buttons like (1..2..3...4..5..etc) with out next, previous, first, last buttons. Can any body let me know if it is posible thorugh standardsetcontroller methods or how? My below code only satisfies my requirement to some extent.

controller

public class standardsetctrl {

 Public List<categoryWrapper> categories {get;set;}
    Public Account acc {get; set;}     
    public String accID;    
public ApexPages.StandardSetController con {
        get {
            String accID=  ApexPages.currentPage().getParameters().get('acId');
            acc=[select name,id,phone,website,Industry from account where id=:accID];
                                   if(con == null) {
                con = new ApexPages.StandardSetController(Database.getQueryLocator([Select Id, Name, Phone, Email FROM Contact where AccountID=:accID Order By Name]));             
           con.setPageSize(5);                
             }
            return con;           
        }
        set;
}
  public List<CategoryWrapper> getCategories() {
        categories = new List<categoryWrapper>();
              for (Contact category : (List<Contact>)con.getRecords()) {
            categories.add(new CategoryWrapper(category));
        }
        system.debug('cons1'+categories.size());
        return categories;
    }
public pagereference process(){         
         List<Contact> contactsDel=new List<Contact>();
 for (CategoryWrapper cw : categories) {
             if (cw.checked) {
                 contactsDel.add(cw.cat);
             }            
               }
             if(contactsDel!=null){
         delete contactsDel;
categories.clear();
getCategories();
      }           
          PageReference p = new PageReference(ApexPages.currentPage().getUrl());
          p.setRedirect(true);     
         return p ;   
     }
     public Integer totalPages {
get {
Integer currPageNumber = con.getPageNumber();
con.last();
Integer totalPages = con.getPageNumber();
con.setpageNumber(currPageNumber);
return totalPages;
}
set;
}

        public Boolean hasNext {
        get {
            return con.getHasNext();
        }
        set;
    }

    // indicates whether there are more records before the current page set.
    public Boolean hasPrevious {
        get {
            return con.getHasPrevious();
        }
        set;
    }

    // returns the page number of the current page set
    public Integer pageNumber {
        get {
            return con.getPageNumber();
        }
        set;
    }
    public void first() {
         con.first();
     }
     // returns the last page of records
     public void last() {
         con.last();
     }

     // returns the previous page of records
     public void previous() {
         con.previous();
     }

     // returns the next page of records
     public void next() {
         con.next();
     }  
  // returns the PageReference of the original page, if known, or the home page.
     public void cancel() {
         con.cancel();
     }
public class CategoryWrapper {
        public Boolean checked{ get; set;}
        public Contact cat { get; set;}

        public CategoryWrapper(){
            cat = new Contact();
            checked = false;
        }
        public CategoryWrapper(Contact c){
            cat = c;
            checked = false;
        }
    }
}

vf page:

<apex:page controller="standardsetctrl">
    <apex:form >
        <apex:pageBlock >
    <apex:pageBlockSection columns="2">
    <font>
        <apex:facet name="header">
            <span style="color:black">Account details</span>
        </apex:facet>     
    </font> 
        <apex:outputField value="{!acc.name}"/>
        <apex:outputField value="{!acc.phone}"/>
        <apex:outputField value="{!acc.Website }"/>
        <apex:outputField value="{!acc.Industry}"/>
    </apex:pageBlockSection>
    </apex:pageBlock>
    <apex:pageBlock title="Contacts" id="pbt">     
        <apex:pagemessages />        
      <apex:pageBlockSection columns="1" id="ps">
      <font>
        <apex:facet name="header">
            <span style="color:black">Contact - Page #{!pageNumber}of {!totalPages}</span>
        </apex:facet>     
      </font>
      <apex:outputPanel id="pb1">
        <apex:pageBlockTable value="{!Categories}" var="c" id="pg">
          <apex:column width="25px">                        
                        <apex:inputCheckbox value="{!c.checked}" id="inputId"/>
                    </apex:column>
          <apex:column value="{!c.cat.Name}" headerValue="Name"/>
           <apex:column value="{!c.cat.phone}" headerValue="phone"/>
            <apex:column value="{!c.cat.email}" headerValue="email"/>
        </apex:pageBlockTable>        
        </apex:outputPanel>        
      </apex:pageBlockSection>
           <apex:pageBlockButtons location="top">
        <apex:commandButton action="{!process}" value="Delete" rerender="pbt" />         
      </apex:pageBlockButtons>  
    </apex:pageBlock>
    <apex:panelGrid columns="4">
    <apex:commandLink action="{!first}" dir="RTL">first</apex:commandlink>
    <apex:commandLink action="{!previous}" rendered="{!hasPrevious}" Dir="LTR">previous</apex:commandlink>
    <apex:commandLink action="{!next}" rendered="{!hasNext}">next</apex:commandlink>
    <apex:commandLink action="{!last}">Last</apex:commandlink>
    </apex:panelGrid>  
    </apex:form>
</apex:page>
1
  • Have you checked out Datatables.net? Great plugin that may save you a lot of work
    – Eric
    Commented Dec 27, 2015 at 15:27

1 Answer 1

8

Using a wrapper class with a set controller is actually pretty simple, but requires a few changes to your code.

First, your controller wants to know which records are selected, so you'd start your controller off with a simple collection (I'd prefer a Set<Id>, personally).

public class PageController {
    public Set<Id> selectedRecordIds;
    public PageController() {
        selectedRecordIds = new Set<Id>();
    }
    // More code coming
}

Next, you need a wrapper class that can manipulate the selected values. Since we're using a non-static variable (because otherwise we lose state), we need a reference to the controller class we can use:

public class Wrapper {
    PageController ctrl;
    public Contact record { get; set; }
    public Wrapper(PageController controller, Contact contactRecord) {
        ctrl = controller;
        record = contactRecord;
    }
    // Not quite done yet...
}

Now, inside the wrapper, we want to manipulate the selected values, so we'll add a bit more code:

// continuing from above...
public Boolean selected { 
    get { return ctrl.selectedRecordIds.contains(record.Id); }
    set { if(value) {
              ctrl.selectedRecordIds.add(record.Id);
          } else {
              ctrl.selectedRecordIds.remove(record.Id);
          }
        }
    }
}

The wrapper class is now done. The only part left is to build a list of wrappers when the page shows a list of records:

public Wrapper[] getRecordsFromCurrentPage() {
    Wrapper[] results = new Wrapper[0];
    for(Contact record: con.getRecords()) {
        results.add(new Wrapper(this, record));
    }
    return results;
}

Which you'd iterate over normally. Note that there is no need for a corresponding setter function, it "just works." Changing pages preserves the selections across any number of records, and uses very little view state per record (basically, the cost of an Id).

To "deselect all", just clear the set. To set all, though, you'd want to extract the ID values from every record in the list and add them to your set. It'd probably more efficient to just replay the query and get the set from a map:

selectedRecordIds = new Map<Id, Contact>([SELECT ... FROM Contact WHERE ...]).keySet();

When using the StandardSetController, remember that records can change from when you started, so you'll probably want to verify that the controller is still holding the correct record ID values before you attempt to perform an update.

3
  • doesn't the getRecordsFromCurrentPage() need a return results; line? Also, as an aside, if the code wanted to, say, iterate over the wrappers to find all wrapped items meeting some filter, the wrappers get rebuilt
    – cropredy
    Commented Aug 8, 2019 at 16:48
  • @cropredy yes, there was a missing line of code... fixed. getRecordsFromCurrentPage() is meant for display purposes in VF. You'd work with the records directly (from the controller) if you were interested in finding particular records.
    – sfdcfox
    Commented Aug 8, 2019 at 17:14
  • imagine a second getter in the controller Boolean getHasAnInterestingWrapper() {iterate over getRecordsFromCurrentPage and return true/false;} will build the wrappers twice in the same transaction initiated by the VF page when needing to display the wrappers and conditionally render a button based on hasAnInterestingWrapper
    – cropredy
    Commented Aug 8, 2019 at 18:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .