1

I see many examples of what a wrapper class is but I'm having hard time understanding it, can anyone please explain me what a wrapper class exactly is (neat and clear explaination). And flow of execution of below/ any good example.

<apex:page controller="AccountSelectClassController" sidebar="false">
    <script type="text/javascript">
        function selectAllCheckboxes(obj,receivedInputID){
            var inputCheckBox = document.getElementsByTagName("input");
            for(var i=0; i<inputCheckBox.length; i++){
                if(inputCheckBox[i].id.indexOf(receivedInputID)!=-1){
                    inputCheckBox[i].checked = obj.checked;
                }
            }
        }
    </script>
    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockButtons >
                <apex:commandButton value="Show Selected Accounts" action="{!processSelected}" rerender="table2"/>
            </apex:pageBlockButtons>

            <apex:pageblockSection title="All Accounts" collapsible="false" columns="2">

                <apex:pageBlockTable value="{!wrapAccountList}" var="accWrap" id="table" title="All Accounts">
                    <apex:column >
                        <apex:facet name="header">
                            <apex:inputCheckbox onclick="selectAllCheckboxes(this,'inputId')"/>
                        </apex:facet>
                        <apex:inputCheckbox value="{!accWrap.selected}" id="inputId"/>
                    </apex:column>
                    <apex:column value="{!accWrap.acc.Name}" />
                    <apex:column value="{!accWrap.acc.BillingState}" />
                    <apex:column value="{!accWrap.acc.Phone}" />
                </apex:pageBlockTable>

                <apex:pageBlockTable value="{!selectedAccounts}" var="c" id="table2" title="Selected Accounts">
                    <apex:column value="{!c.Name}" headerValue="Account Name"/>
                    <apex:column value="{!c.BillingState}" headerValue="Billing State"/>
                    <apex:column value="{!c.Phone}" headerValue="Phone"/>
                </apex:pageBlockTable>

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

Apex Class:

public class AccountSelectClassController{

    //Our collection of the class/wrapper objects wrapAccount
    public List<wrapAccount> wrapAccountList {get; set;}
    public List<Account> selectedAccounts{get;set;}

    public AccountSelectClassController(){
        if(wrapAccountList == null) {
            wrapAccountList = new List<wrapAccount>();
            for(Account a: [select Id, Name,BillingState, Website, Phone from Account limit 10]) {
                // As each Account is processed we create a new wrapAccount object and add it to the wrapAccountList
                wrapAccountList.add(new wrapAccount(a));
            }
        }
    }

    public void processSelected() {
    selectedAccounts = new List<Account>();

        for(wrapAccount wrapAccountObj : wrapAccountList) {
            if(wrapAccountObj.selected == true) {
                selectedAccounts.add(wrapAccountObj.acc);
            }
        }
    }

    // This is our wrapper/container class. In this example a wrapper class contains both the standard salesforce object Account and a Boolean value
    public class wrapAccount {
        public Account acc {get; set;}
        public Boolean selected {get; set;}

        public wrapAccount(Account a) {
            acc = a;
            selected = false;
        }
    } 
}

And I saw some cases where 2 wrapper classes were created within a class. And a LIST of one is being used in the other class, how does that exactly work. Thanks in advance.

2 Answers 2

2

Summary

A wrapper class is used by developers to provide associated metadata or functions for a record or a list of records (usually the latter), which has some purpose during the lifecycle of the page but usually doesn't need to be saved to the database.

Details

SObjects represent database tables. You can use them generically, or you can use them as concrete versions, such as Account, Contact, or custom objects. However, developers often have a need to associate metadata with each record, such as selecting a number of records to modify or delete at once, or calculate some value that isn't explicitly defined at the database level.

In your example class, the account is being wrapped along with a boolean value that will be (presumably) represented as checkboxes, where the user can select a number of checkboxes and apply some function to all of the selected accounts at once. There are other ways to accomplish this goal, but wrapper classes tend to be the easiest representation of metadata, as well as the most commonly used pattern. You can also associate functions with each record that can be called to operate on a specific record within a list, without passing parameters to the function.

Wrapper classes may also "marry" two or more types of records together that are physically defined as separate entities, but operate on the page as if they were one concatenated record. This can be easier to work with from a developer's standpoint, because only one loop is necessary to render the data, and it's all kept in order internally.

Purpose of Example

This code is purely for the sake of example. The processor function doesn't do anything, and perhaps that's why you're getting confused. While it shows how to build a list of accounts from the ones that were selected, nothing is done with them, so this is basically an elegant no-op. A more useful example might be as follows:

<apex:page controller="DeleteFromListController">
<apex:form>
<apex:pageBlock>
    <apex:pageBlockButtons>
        <apex:commandButton action="{!deleteSelected}" value="Delete Selected" />
    </apex:pageBlockButtons>
    <apex:pageBlockTable value="{!accounts}" var="row">
        <apex:column><apex:inputCheckbox value="{!row.selected}" />
        <apex:column value="{!row.record.name}" />
        <apex:column value="{!row.record.accountnumber}" />
    </apex:pageBlockTable>
  </apex:pageBlock>
</apex:form>
</apex:page>

And the controller:

public with sharing class DeleteFromListController {
    // shows our wrapper
    public AccountWrapper[] accounts { get; set; }
    // contains an account and a checkbox value
    public class AccountWrapper {
        public boolean selected { get; set; }
        public account record { get; set; }
        public AccountWrapper(Account record) {
            this.record = record;
            selected = false;
        }
    }
    // builds a list of accounts
    public void refreshList() {
        accounts = new AccountWrapper[0];
        for(Account record:[SELECT Id, Name, AccountNumber FROM Account LIMIT 10]) {
            accounts.add(new AccountWrapper(record));
        }
    }
    // default constructor, load some records
    public DeleteFromListController() {
         refreshList();
    }
    // loop through, find any selected records, and delete them
    public void deleteSelected() {
        Account[] records = new Account[0];
        for(AccountWrapper wrapper: accounts) {
            if(wrapper.selected) {
                records.add(wrapper.record);
            }
        }
        delete records;
        // regenerate the list afterwards
        refreshList();
    }
}

Note, there's no error checking here, but this example is otherwise fully functional (e.g. you can actually test it in your org and start deleting accounts today).

0

Essentially it's an inner class or a nested class or a subclass within the body of another class. It helps define a template for an object (instance of that class) that you can use later in your code. Same as you set properties to standard/custom sObjects and the same way you're interacting with them, the inner class helps you define a custom type of an object with its own properties.

You gave a perfect example - checking account records on a page. Instead of having a list of accounts and a Map <Id, Boolean> to keep track of the selected accounts, you can combine the sObject account together with another boolean variable and have them in one place. You know which account is selected without having nested loops and iterations through lists and maps comparing IDs in order to find the selected record.

You must log in to answer this question.

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