Visualforce components

Here is an example that illustrates a couple of things that I didn’t understand from the standard documentation:

  • Think of components as more like functions than included sections of text. It took me some time (with the apex:commandLink doing nothing when clicked) before I realized the page using the component needs to pass its controller action such as “{!addTask}” via an ApexPages.Action attribute.
  • You can pass in one dimensional lists or arrays (of SObjects or your own classes) providing you use the array notation.
<apex:component>

    <apex:attribute name="title" type="String" required="true" description=""/>
    <apex:attribute name="list" type="JournalItem[]" required="true" description=""/>
    <apex:attribute name="addAction" type="ApexPages.Action" required="true" description=""/>

    <apex:pageBlockSection title="{!title} ({!list.size} Items)" columns="1">
        <apex:pageBlockTable value="{!list}" var="item">
            <apex:column headerValue="Title" style="white-space: nowrap">
                <apex:outputLink value="/{!item.Id}/e?saveURL={!$CurrentPage.URL}&retURL={!$CurrentPage.URL}">
                    {!item.Title}
                </apex:outputLink>
            </apex:column>
            <apex:column headerValue="Content">
                <apex:outputText value="{!item.startOfText}"/>
            </apex:column>
        </apex:pageBlockTable>
        <apex:panelGrid columns="2">
            <apex:outputText value="Add "/>
            <apex:commandLink value="Task" action="{!addAction}"/>
        </apex:panelGrid>
    </apex:pageBlockSection>

</apex:component>

Also unfortunately many of the standard components insist that they are nested inside some other standard component. So, for example, if you have a complicated apex:pageBlockTable or apex:column that you want to have multiple times in your page and so go to create a component, you will be unable to do so with an error like “Error: <apex:pageBlockTable> must be contained in <apex:pageBlock> or <apex:pageBlockSection>” returned when you save the component. This really limits the opportunities to reduce duplication in pages.

But it is possible to build components out of other components.

Finally there is an allowDML=”true” flag on an apex:component. If this flag is not present and the component invokes an action that tried to modify data a “DML currently not allowed” error results. See the apex:component documentation for the explanation…

Advertisements

6 thoughts on “Visualforce components

  1. Nice post 🙂 Not sure if this might sort your problem but you could create the content of a column (for example) in a custom component and then drop this into a standard column component. After a few months of dev on the platform I find that I use very few of the standard components, but I use the CRM very little ( as opposed to using the Force.com development platform).

    • At the moment we are using a mixture of custom pages and default UI pages and so to get consistent styling without having to reverse engineer the styles (which may also change in future) we are using the standard apex:xxxx components rather than direct HTML. So its not that we are using the CRM functionality so much as that we are using the CRM UI themes and so e.g. we can switch on the new Spring 10 theme and everything works.

      But (if I understand you correctly), the possibility remains to create a custom component out of HTML tags that avoids the nesting constraints. I think we may end up doing that in some cases – thanks.

      Incidentally, its hard to know if the nesting constraints are accidental (a bug) or part of the architecture as there is little to nor architectural documentation.

      • I think it’s part of the architecture, although I agree it’s not clear.. I imagine it’s similar to HTML TableRows having to be nested with Tables.

        I’ve used components in two ways (which overlap), either to encasulate functionality & display e.g. record lines, or simply as a piece of template code (no controller) e.g. page headers & footers.

    • If the component is named “TaskTable” then you can use it multiple times in multiple pages like this:

      <c:TaskTable title=”Tasks” list=”{!actionPlanTasks}” addAction=”{!addActionPlanTask}” />

      passing in different arguments as needed.

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