Monday, May 20, 2013

Showing images in a list view - A picture IS worth a thousand words!


If you have been using Salesforce a lot, you are probably familiar with the list view by now.  That is what gets displayed when you click a tab, showing you a list of records that your organization has for an object.













You may have also tried to edit or even create a new view because the default view is not quite what you want.  You may want different data, or you may want the information presented in slightly different order.  However, no matter how you customize it, it's still showing you texts after texts after texts, which is rather dull.  You may have a list of all inventories you have in your warehouse, including its inventory count.  Unless you sort your list by quantity,  it may not be straightforward to see which inventory is running low.

Here is the good news:  you can actually use a few simple tricks to display some images in your list view.  Here is how.

For this example that I am using to track my inventory, let's say I want to use different colors to represent the level of inventory count.  So if my count for a product is less than 200, I should pay some attention to it; and if it falls below 50, I really need to do something immediately.  This is like the traffic light analogy.  Green represents safe, referring to merchandise that I have abundant supply of.  Yellow represents attention, referring to stock level between 50 and 200.  Lastly red represents warning, referring to stock level below 50.

Do you know that Salesforce comes with some predefined images?  You can find some of them by reading this document (NOTE:  it is a document from Salesforce dated back in 2005 so some information may have become out of date).  If you want more variety, you can download a Graphics Pack app from AppExchange that has even more images you can use.

For this example, I'm going to use the traffic lights which are readily available at Salesforce.com:


/img/samples/flag_green.gif

/img/samples/flag_yellow.gif

/img/samples/flag_red.gif
In order to use the image files, all you need to do is to create a formula field in the Merchandise__c object.  The output of the formula field will be a string that indicates the name of the filename of the image.  I am going to call this formula field Quanaity_Level__c.

This formula is going to make use of two functions, image() and if().

If you have done some programming at all, you probably can guess if().  The if(condition_test, condition_true, condition_false) function takes three arguments.  The first argument condition_test is the condition to check, the second argument condition_true is what you want to return if the first argument is true, and the third argument condition_false is what you want to return if the first argument is false.

The function image(image_url, image_text, image_height, image_width) takes four arguments.  The first argument image_url is the url to the image file.  The second argument image_text is the text to display if the image does not load for some reasons.  The last (optional) arguments image_height and image_width represent the size of the image.  The image shrinks or stretches if the size specified here does not match the actual size of the original image.  If these two arguments are omitted, the image will be rendered at its original size.

What we are trying to do is to check the Quanaity__c field of the Merchandise__c object.  With careful coding, applying the above business logic I outlined, this is what the formula field will look like:
if(Quantity__c >= 200, 
  image('/img/samples/flag_green.gif', 'Abundant'),
  if(50 <= Quantity__c && Quantity__c < 200,   
    image('/img/samples/flag_yellow.gif', 'Attention!'),
    image('/img/samples/flag_red.gif', 'WARNING!!!')
  )
)

Let's say you have already defined a new list view called "Merchandise with Quantity".  It may look like this:



After you have created this formula field, all you need to do is to include it in your list view definition.  Your list will look like this.

Of course, you don't really need to have an image every line.  You might only want to show the flag when your merchandise has gone down to dangerous level, because that will really make your merchandise with a low inventory count stand out.

Do you know how to change your formula field so you can produce this list?




Lastly, keep in mind that formula fields can not only be used in your list view.  Once you have created it, it can be used in many places, such as in your form (either edit page or detail page) or even reports.  Let's go and explore!

Wednesday, May 1, 2013

BUG REPORT: Dynamic Visualforce Bindings


Before I start, I encourage you to go over Salesforce’s Visualforce Developer’s Guide which you can find here.  There is a section called “Dynamic Visualforce Bindings” that already provides the syntax and more information about the topic that I am discussing today. 

If you don’t have time to read the Developer’s Guide, or if you just want to quickly glance at what I have to say today, then still please let me quickly talk about what exactly Dynamic Visualforce Binding is.  It is an extremely powerful tool to build dynamic pages at run time.

We all know that Visualforce is the “V” (view) part of the MVC paradigm that Salesforce uses.  It indicates what the user interface of a page is like.  A traditional Visualforce page denotes how the page should look like, what information is displayed, and in what order.  In other words, a Visualforce page dictates what information the users see and how they see it.  The person that wrote the Visualforce page is in the driver's seat.
  
However, imagine this use case.  What if you want to display a list of accounts, but you also want to give your users the flexibility to determine what information about the account they want to see.  You may want to present a list of account related fields, and the users can select what fields they want to see and in what order.  Having to program that logic can be a nightmare:  the users may choose one field or ten fields, the users may choose Name first this time and then Name last next time.  There are so many possibilities and combinations that, if not programmed carefully, your code can become nothing but an endless list of if-then-else statements.

Enters Dynamic Visualforce Binding.

Let's just quickly see what a regular Visualforce page looks like.  As an example I want to display the account name, account number, annual revenue and ticker symbol of a list of accounts.  To do that, all you need to do is a very simple Visualforce page like this:
<apex:page standardController="account" recordSetVar="accounts">
    
    <apex:pageBlock >
        <apex:pageBlockTable value="{!accounts}" var="a">
            <apex:column value="{!a.Name}" />
            <apex:column value="{!a.AccountNumber}" />
            <apex:column value="{!a.AnnualRevenue}" />
            <apex:column value="{!a.TickerSymbol}" />
        </apex:pageBlockTable>
    </apex:pageBlock>
    
</apex:page>

Your page will look like this:










In order to use Dynamic Visualforce Binding, you need a little help from a controller.  (I know it can be a turnoff,  but no pain no gain!)

Let's take a look at the controller (again, I don't want to divulge into the syntax.  Please refer to the Developer's Guide for the detailed syntax.  I just want to show you how little code is required to unleash the power of Dynamic Visualforce Binding.)


public class AccountListDynamic
{
    // constructor that simply adds the list of fields 
    // for the account.
    public AccountListDynamic(ApexPages.StandardSetController controller)
    {
        controller.addFields(accountFieldList);
    }

    // accountFieldList is a property.  It is a list of 
    // strings and each element in the list is the API 
    // name of the field that I want to display.  This list
    // is read-only.
    public List<String> accountFieldList
    {
        get
        {
            if (accountFieldList == null)
            {
                accountFieldList.add('Name');
                accountFieldList.add('AccountNumber');
                accountFieldList.add('AnnualRevenue');
                accountFieldList.add('TickerSymbol');
            }
            return accountFieldList;
        }
        private set;
    }

}

I hope the class is quite self-explanatory.  It is an extended controller (hence the ApexPages.standardSetController parameter in the constructor of the class).  All that we are achieving here is to pass an array of account related field names (API names) and expose the list to the Visualforce page.

The Visualforce page now looks like this:
<apex:page standardController="account" recordSetVar="accounts" extensions="AccountListDynamic">
    <apex:pageBlock >
        <apex:pageBlockTable value="{!accounts}" var="a">
            <apex:repeat value="{!accountFieldList}" var="f">
                <apex:column value="{!a[f]}" />
            </apex:repeat>
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>

The hardest part to understand is probably a[f] above.  "a" is a loop variable for each account in the list.  "f" is a loop variable for each field to display.  Therefore to simply put, a[f] refers to the value of a specific field for a specific account.

So, sure now you have the controller that makes things look a little more complicated, but did you notice the controller now handles the list of fields.  All the Visualforce page does is to simply take that list of fields and displays the relevant data; you do not have any field names hardcoded in the Visualforce page at all!

Now, going back to our use case.  Let's say you want to show the user a list of all account related fields, so that the user has the ability to choose which fields they want to display and the order the fields are to display.

You will need a separate Visualforce page for that.  Once you have built this new Visualforce page for that, then all you need to do is to capture the information in your controller.  Then the Visualforce page shown above again can be used to display the information.

This is exactly what the example in the Developer's Guide, in section "Using Dynamic References for a User-Customizable Page", is about.  It is an excellent read, and I urge you to take a look at this topic.

The most unfortunate thing is that this function is not stable.  I have got the code to work in some environments but fail in others.

I followed the example as per the Developer's Guide and this is the error I received:



I have talked to Salesforce and it is now officially under the "Known Issues" list.  If you are interested, you can take a look at this page for more details.  If you can replicate this error too, I strongly encourage you to click the "This Issue Affects Me" button.  Note that the example there is quite different, but it still exposes the defect related to Dynamic Visualforce Binding.