Wrapper (or Helper) Classes – What can I do with them?


Wrapper Classes (I’ll refer to them in here as “WCs”) are a wonderful tool for so many things, but are mostly unknown or under-utilized by a lot of SFDC developers that I’ve met.  Recently on #askForce someone said they were looking for a good article on how WCs can be used without immediately diving into technical specs or the deep nitty-gritties but was unable to find anything, so I said CHALLENGE ACCEPTED!

The name “Wrapper Class” is exactly that.  It’s essentially an object that you can “wrap” data within.  Easy analogy to the real world?  Go buy a coffee maker at Sears.  The box it comes in?  That’s a wrapper class.  You take 50 of those coffee maker boxes on a shipping palette, (back to Salesforce lingo) you have a List<wrapperClass>.

I love WCs.  I would estimate that 80% of my overall projects utilize WCs in one way or another.  My primary use case for them is when I am creating interactive / rich grids of data.

What do I mean?

Typically when displaying a list of data, you create a GETer or a public List<whatever> variable and stick it in a datatable / repeat / etc.  That method totally works, but it’s pretty flat and without some additional wizardry via VF pretty non-functional.  (display-only)

What if I need to render a checkbox, picklist, or some other control / data point that isn’t necessarily on the record natively?  I don’t want to have to go and create a bunch of sObject fields just to tell whether or not I’ve put a checkmark in a box or if certain fields are filled out to render a section.

Enter WCs.

Code Example:  (I take no responsibility for the accuracy of my pseudo-code…Wordpress isn’t an IDE!)

Here’s a standard List<Account> implementation…

List<Account> lstAccounts = [SELECT Id, Name, Field1__c, Field2__c FROM Account WHERE some_field__c = ‘some value’];

<apex:pageBlockTable value=”{!lstAccounts}” var=”a”>
<apex:column headerValue=”Id” value=”{!a.Id}” />
</apex:pageBlocktable>

That totally works and is a valid use case – but let’s get a little fancier.  Let’s throw in a checkbox column and an OutputPanel based on a Boolean value.  My use case here is that I want to have a list of records with checkboxes, and then through a CommandButton perform some sort of action only on the “checked” ones.  Sound similar to a multi-select list view in Salesforce now?  Yup.

First off, we need to think about what we want to put in the box (if you just went out and made a box…how would you know your contents would fit??).  Keeping with our use case, I would say that:

  • I want to have an sObject record
  • I want to have a Boolean value to tell me if it’s “checked” or not

Let’s first create our WC:

public class hClsAccount {

// declare variables just like a grown-up class!
public Account acct {get;set;}
public Boolean bolChecked {get;set;}

// constructor, again just like a grown-up class.
public hClsAccount(Account passAccountRecord) {

// Set initial variables
acct = passAccountRecord;
bolChecked = false;

}
}

With that created, we could just create a GETer of a List<hClsAccount> and display that on our page, but what fun would that be?  We couldn’t go back and run through it just using a GETer.  What I usually do is declare a List<helperClass> at the top of my parent class.

List<hClsAccount> lstAccounts {get;set;}

Within a method (or constructor, VF action, etc) you can fill this list.  Putting the sObject record in the WC constructor is just a script line-saving measure – you don’t have to.  The end result of this method is a fully populated list that you can now reference in VF.

public void fillHelperClass {

// Re-Instantiate List
lstAccounts = new List<hClsAccount>();

// Run your sObject query
for(Account a : [SELECT Id, Name, Field1__c, Field2__c FROM Account WHERE some_field__c = ‘some value’]) {

// Instantiate Wrapper Class
hClsAccount clsA = new hClsAccount(a);
lstAccounts.add(clsA);
}
}

Now, over to VF.  You’ll note that normally when accessing a List<sObject> in an apex:pageBlockTable, you refer to fields in the table as <var>.<field>.  With a wrapper class, you now have another layer in here – the object WITHIN the WC.  Looking above to our WC, to get the “Account Name” field, instead of “{!a.Name}” like you would normally, you’d do “{!a.acct.Name}” – “a” = your PBT var, “acct” = the sObject WITHIN the WC, and then “Name” = the field in the sObject.

<apex:pageBlockTable value=”{!lstAccounts} var=”a”>

<apex:column headerValue=”Do Something?”>
<apex:inputCheckbox value=”{!a.bolChecked}”
</apex:column>

<apex:column headerValue=”Name” value=”{!a.acct.Name}” />

<apex:column headerValue=”Field 1″ value=”{!a.acct.Field1__c}” />

<apex:column headerValue=”Field 2″ value=”{!a.acct.Field2__c}” />

</apex:pageBlockTable>

Looking pretty slick eh?  Yeah.  =)

Now – how to process those records you’ve checked…

public void processCheckedRecords() {

for(hClsAccount h : lstAccounts) {

if(h.bolChecked) {
// Do your logic.
String strAccountName = h.Acct.Name;
}

}

}

What’s next?  Really anything you can think of!  Picklists, boolean logic to render/not render columns, heck…even CSS if you are feeling “violate-y of the MVC”.  You can even have methods IN your WC to do certain things just as you’d do in your parent class.  Pretty slick.  =)

Seems pretty easy reading a blog – go ahead and try it out, give me a shout if you have questions.  (Twitter, comment below, whatever.)

Advertisements

14 thoughts on “Wrapper (or Helper) Classes – What can I do with them?

  1. Thank you very much for this article, it helped me a lot.
    But I think there is a little mistake.
    you wrote:
    public void fillHelperClass{
    instead of
    public void fillHelperClass () {

  2. Rather than records can we get fields like we can enter values in that fields and save it..Is using wrapper it is possible??

    • Writing a test for a wrapper/inner class is really no different than covering other “normal” methods or variables – all you have to do is to call it (or preferably a method that calls it) and fill it in.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s