Thursday, 30 August 2012

Using Inner Classes in an Apex Controller

In the last lesson, you created a custom controller for your Visualforce catalog page. But your controller passes custom objects from the database directly to the view, which is not ideal. In this lesson, you’ll refactor your controller to more correctly use the MVC design pattern, and add some additional features to your page.
  1. Click StoreFrontController to edit your page’s controller code.
  2. Revise the definition of the class as follows and then click Quick Save.
    public class StoreFrontController {
    
        List<DisplayMerchandise> products;
        
        public List<DisplayMerchandise> getProducts() {
            if(products == null) {
                products = new List<DisplayMerchandise>();
                for(Merchandise__c item : [
                        SELECT Id, Name, Description__c, Price__c, Total_Inventory__c 
                        FROM Merchandise__c]) {
                    products.add(new DisplayMerchandise(item));
                }
            }
            return products;
        }
        
        // Inner class to hold online store details for item 
        
        public class DisplayMerchandise {
    
            private Merchandise__c merchandise;
            public DisplayMerchandise(Merchandise__c item) {
                this.merchandise = item;
            }
    
            // Properties for use in the Visualforce view 
        
            public String name {
                get { return merchandise.Name; }
            }
            public String description {
                get { return merchandise.Description__c; }
            }
            public Decimal price {
                get { return merchandise.Price__c; }
            }
            public Boolean inStock {
                get { return (0 < merchandise.Total_Inventory__c); }
            }
            public Integer qtyToBuy { get; set; }
        }
    }
  3. Click Catalog to edit your page’s Visualforce code.
  4. Change the column definitions to work with the property names of the new inner class. Replace the existing column definitions with the following code.
    <apex:column headerValue="Product">
        <apex:outputText value="{!pitem.Name}"/>
    </apex:column>
    <apex:column headerValue="Description">
        <apex:outputText value="{!pitem.Description}"/>
    </apex:column>
    <apex:column headerValue="Price">
        <apex:outputText value="{!pitem.Price}"/>
    </apex:column>
    
    The outputField component works automatically with sObject fields, but doesn’t work at all with custom classes. outputText works with any value.
  5. Click Save to save your changes and reload the page. You’ll notice that the price column is no longer formatted as currency.
  6. Change the price outputText tag to the following code.
    <apex:outputText value="{0,number,currency}">
        <apex:param value="{!pitem.Price}"/>
    </apex:outputText>
    The outputText component can be used to automatically format different data types.
  7. Verify that your code looks like the following and then click Save.
    <apex:page controller="StoreFrontController" tabStyle="Merchandise__c">
    
        <apex:pageBlock title="Our Products">
    
            <apex:pageBlockSection columns="1">
    
                <apex:pageBlockTable value="{!products}" var="pitem">
                    <apex:column headerValue="Product">
                        <apex:outputText value="{!pitem.Name}"/>
                    </apex:column>
                    <apex:column headerValue="Description">
                        <apex:outputText value="{!pitem.Description}"/>
                    </apex:column>
                    <apex:column headerValue="Price" style="text-align: right;">
                        <apex:outputText value="{0,number,currency}">
                            <apex:param value="{!pitem.Price}"/>
                        </apex:outputText>
                    </apex:column>
                </apex:pageBlockTable>
    
            </apex:pageBlockSection>
    
        </apex:pageBlock>
    
    </apex:page>
    Your catalog page will look something like this.
    Product catalog page with custom controller, before cart

Tell Me More...

  • The DisplayMerchandise class “wraps” the Merchandise__c type that you already have in the database, and adds new properties and methods. The constructor lets you create a new DisplayMerchandise instance by passing in an existing Merchandise__c record. The instance variable products is now defined as a list of DisplayMerchandise instances.
  • The getProducts() method executes a query (the text within square brackets, also called a SOQL query) returning all Merchandise__c records. It then iterates over the records returned by the query, adding them to a list of DisplayMerchandise products, which is then returned.

No comments:

Post a Comment