Wrapper Classes and Salesforce

Wrapper Classes and Salesforce

Salesforce as a platform is highly object oriented and strongly typed environment.

Salesforce Org Back-office is simply a UI representation of a relational database, with Apex as a C# like language to handle data structures; and SOQL as the query language which combines data querying with API usage.

The general architecture of salesforce is parallel to a database: Objects are the tables, Fields are the columns and Records are the rows (an instant of the object).

With numerous types of classes to choose from during development (about 30 on MavensMate), Salesforce has its own implementation of the MVC structure.

  • The Model - the object - defined through the salesforce UI and kept as metadata viewed as xml.
  • The View - made out of Visualforce pages and components or Lightning elements.
  • The controller - an Apex class with a similar extend to other MVC controllers, passing data based on existing Models to the view elements.

While other OOP languages commonly refer to classes as an objects, in Salesforce only data structures that exist in the database are considered objects.

If sticking to the basic way of handling data in Salesforce, a developer would be restricted to data structures (sets and lists) of a single object type, while the relation between these structures will be kept in a designated object (that would handle master-details relation), or within another data structure (maps). Using this basic technique for handling multiple related objects, even when only one field is required from each, can become very confusing very fast.

Consider the following structure:

Contact

|___ Orders

        |___ Order Line

Each Contact can have multiple Orders which can have multiple Order Lines.

This nested and dependent structure, will be best represented in a NoSQL database, or JSON.


Wrapper Classes to the rescue!

You can think about wrapper classes as classes that quite literally wrap together data (mostly from existing objects) into a new type.

This type will not be considered a SObject, as it doesn't have a database representation and its fields will not have an API name (suffix __c). They are valid Object nonetheless.

Advantages:

  • Just like a JSON structure, the structure of your wrapper classes would correspond to the visualization of the data on the page.
  • Eliminates the need to pass Map structures to the view elements (as a way of maintaining relation between objects).
  • Better organization, especially when the data levels are nested.
  • No penalty in passing SObject and more extendable to the class constructor.
  • Along with the Transient keyword helps to maintain a smaller view state (when passing data to browser and back) leading to improved performance.
  • One line away from returning a JSON to the view, or the client controller for lightning.


The wrapper classes can be kept within the Controller class, but it might be best if kept separately - so it could be extended and reused easily while avoiding code duplication.

Back to our structure > In the following example the wrapper classes contain a String value and another wrapper class referencing an Salesforce object.

public class ContactOrdersWrapper {
    public string name;
    public List<OrderWrapper> orders;

    // class constructorpublic 
    ContactOrders(Contact c, List<Order> conOrders){
        name = c.Name;
        orders = conOrders;
    }
}


public class OrderWrapper {
    public string name;
    public List<OrderLineWrapper> orderLines;

    // class constructor
    public Order(Order__c o){
        name = o.Name;
        for (oLine : o.Order_Lines__r){
            //No penalty in passing the SObject and more extendable
            orderLines.add(new OrderLineWrapper(oLine.Name));
        }
    }
}


public class OrderLineWrapper {
    public string name;

    // class constructor
    public OrderLine(string n){
        name = n;
    }
}

The Controller:

global class ContactOrderController {

    public ContactOrdersWrapper conOrders {get;set;}
    public List<OrderWrapper> orders {get;set;}
    public static Map<Id, List<Order_Lines__c>> orderLinesByOrderId {get;set;}

    // additional properties if required
    // .
    // .
    // .


    global ContactOrderController() {

        Contact contactWithOrder = [SELECT .....];

        List<Order__c> rawOrders = new List<Order__c>([SELECT .....])

        orderLinesByOrderId = buildOrderLinesByOrderId([SELECT ... FROM Order_Lines__c where OrderId in :ordersAssociatedWithContactSet]);

        // additional logic and queries
        // .
        // .
        // .

        conOrders = new ContactOrdersWrapper(c, orders);
    }
}

The Page:

<apex:page controller="ContactOrderController">
    
    <apex:repeat value="{!conOrders}" var="co" id="conOrdersRepeat">
    
        <apex:outputText value="{!co.name}" />

        <apex:repeat value="{!co.orders}" var="o" id="ordersRepeat">

            <apex:outputText value="{!o.name}" />

            <apex:repeat value="{!o.orderLines}" var="ol" id="orderLinesRepeat">

                <apex:outputText value="{!ol.name}" />

            </apex:repeat>

        </apex:repeat>

    </apex:repeat>

</apex:page>


To sum up :

A wrapper class is a construction of a new type (object) in Apex code, which can combine fields from different objects (your own \ Salesforce) or a bunch of fields - which you need only in Run time (mostly in the view) to achieve your goal.

Wrapper classes provide flexibility and additional control over the data passed to the view or client controllers. From a FrontEnd point of view, the Apex code on the page will be more readable as well as providing additional flexibility when using pure UI components within the repeat statements.

Within Apex, Visualforce and Lightning, wrapper classes can be extremely helpful in achieving many business scenarios, by expanding developers capabilities when customizing applications.

A BIG thanks to Livio Ravetto for his inspiration and help in writing this article.


References: Community posts , discussions, blogs and articles .

To view or add a comment, sign in

More articles by Tzhe'ela Trooper

  • #PressForProgress #IWD 2018 TECH(K)NOW Day

    This is the third Tech(K)NowDay in the past 12 months - a day to celebrate knowledge and new skills. Much like other…

  • MERGING Vs. REBASING

    git merge and git rebase can be used for: Bringing your current feature branch up to speed with the latest updates from…

    4 Comments
  • Vim - the power in your fingertips

    Vim - the power in your fingertips Or How to look like a code-ninja while writing that book you always said you would!…

    2 Comments
  • Recruit . Re-train . Repeat

    As technology continues to evolve so have job roles and the need for new skills. Today’s trades and professions are…

Others also viewed

Explore content categories