Dynamic References to Static Resources Using $Resource

Dynamic references to static resources can be very useful for providing support for themes or other visual preferences.

To reference a static resource using the $Resource global variable, provide the name of the static resource in an expression: {! $Resource[StaticResourceName] }. For example, if you have a getCustomLogo method that returns the name of an image uploaded as a static resource, reference it like this: <apex:image value="{!$Resource[customLogo]}"/>.

This example illustrates how to switch between two different visual themes. First, create a controller extension named ThemeHandler with the following code:
public class ThemeHandler {

    public ThemeHandler(ApexPages.StandardController controller) { }
    
    public static Set<String> getAvailableThemes() {
        // You must have at least one uploaded static resource
        // or this code will fail. List their names here.
        return(new Set<String> {'Theme_Color', 'Theme_BW'});
    }
    
    public static List<SelectOption> getThemeOptions() {
        List<SelectOption> themeOptions = new List<SelectOption>();
        for(String themeName : getAvailableThemes()) {
            themeOptions.add(new SelectOption(themeName, themeName));
        }
        return themeOptions;
    }
    
    public String selectedTheme {
        get {
            if(null == selectedTheme) {
                // Ensure we always have a theme
                List<String> themeList = new List<String>();
                themeList.addAll(getAvailableThemes());
                selectedTheme = themeList[0];               
            }
            return selectedTheme;
        }
        set {
            if(getAvailableThemes().contains(value)) {
                selectedTheme = value;
            }
        }
    }
}
Notes about this class:
  • It has an empty constructor, because there’s no default constructor for controller extensions.
  • Add the name of your uploaded static resource files theme to the getAvailableThemes method. Using Static Resources provides details of how to create and upload static resources, in particular, zipped archives containing multiple files.
  • The last two methods provide the list of themes and the selected theme for use in the Visualforce form components.
Now create a Visualforce page that uses this controller extension:
<apex:page standardController="Account" 
           extensions="ThemeHandler" showHeader="false">

    <apex:form >
    <apex:pageBlock id="ThemePreview" >
      <apex:stylesheet 
          value="{!URLFOR($Resource[selectedTheme], 'styles/styles.css')}"/>

      <h1>Theme Viewer</h1>
      <p>You can select a theme to use while browsing this site.</p>
      
      <apex:pageBlockSection >
          <apex:outputLabel value="Select Theme: " for="themesList"/>
          <apex:selectList id="themesList" size="1" value="{!selectedTheme}">
              <apex:actionSupport event="onchange" rerender="ThemePreview"/>
              <apex:selectOptions value="{!themeOptions}"/>
          </apex:selectList>
      </apex:pageBlockSection>
      
      <apex:pageBlockSection >
      <div class="custom" style="padding: 1em;"><!-- Theme CSS hook -->

          <h2>This is a Sub-Heading</h2>
          
          <p>This is standard body copy. Lorem ipsum dolor sit amet, consectetur 
          adipiscing elit. Quisque neque arcu, pellentesque in vehicula vitae, dictum 
          id dolor. Cras viverra consequat neque eu gravida. Morbi hendrerit lobortis 
          mauris, id sollicitudin dui rhoncus nec.</p>
          
          <p><apex:image 
              value="{!URLFOR($Resource[selectedTheme], 'images/logo.png')}"/></p>

      </div><!-- End of theme CSS hook -->  
      </apex:pageBlockSection>
    
    </apex:pageBlock>
    </apex:form>
</apex:page>
Note the following about this markup:
  • The page uses the Account standard controller, but has nothing to do with accounts. You have to specify a controller to use a controller extension.
  • The first <apex:pageBlockSection> contains the theme selection widget. Using <apex:actionSupport>, changes to the selection menu re-render the whole <apex:pageBlock>. This is so that the <apex:stylesheet> tag gets the updated selectedTheme for its dynamic reference.
  • The theme preference selected here is only preserved in the view state for the controller, but you could easily save it to a custom setting instead, and make it permanent.
  • The zip files that contain the graphics and style assets for each theme need to have a consistent structure and content. That is. there needs to be an images/logo.png in each theme zip file, and so on.

There are only two dynamic references to the $Resource global variable on this page, but they show how to access both stylesheet and graphic assets. You could use a dynamic reference in every <apex:image> tag on a page and completely change the look and feel.

$Label and $Setup are similar to $Resource, in that they allow you to access text values or saved settings that your organization administrator or users themselves can set in Salesforce:
  • Custom labels allow you to create text messages that can be consistently used throughout your application. Label text can also be translated and automatically displayed in a user’s default language.
  • Custom settings allow you to create settings for your application, which can be updated by administrators or by users themselves. They can also be hierarchical, so that user-level settings override role- or organization-level settings.