by Kyle Thornton @knthornt

As much as we try to avoid complexity, we can never really get away from it. When clicks can’t cover it anymore we go to code. But when code becomes more complex than it should, where do we go from there? That’s when we dig a little bit deeper into the Apex and Visualforce toolbox.

At Mavens we face these issues often and this one was no different; a client had an object which could have a parent of the same object. This led to a situation where you could have a hierarchy of indeterminate depth.

DVC figure1.jpg

We needed to display this hierarchy in a Visualforce page. In our controller we used a wrapper class to create the hierarchy. The wrapper would store the parent object with its children objects. Each child object had its own children and this could go n levels deep.

public class recordHierarchy {
    public Record__c detail { get; set; }
    public List<recordHierarchy> children { get; set; }
  
    public recordHierarchy( Record__c thisRecord) {
        this.detail = thisRecord;
        this.children = new List<recordHierarchy>( );
    }
}

In Visualforce we might render this out in such a way:

<apex:outputPanel>
<apex:repeat var=“record” value=“{!records}”>
	<apex:IntputText value=“record.detail.Name/>
	
	<apex:repeat  var=“childRecordLevel1” value=“record.children”>
		<apex:InputText value=“childRecordLevel1.detail.Name/>
		
		<apex:repeat var=“childRecordLevel2” value=“childRecordLevel1.children”>
			<apex:InputText value=“childRecordLevel2.detail.Name/>
			
				<apex:repeat … /> <!- - you get the point - - >
		</apex:repeat>
	</apex:repeat>
</apex:repeat>
</apex:outputPanel>

You might recognize the problem right away. We have a hierarchy of indeterminate depth and in order to render out that data model we need to have a sufficient number of nested repeat components. But what is the “sufficient number?” Our customer could tell us that sufficient is 10. But what if in the future the depth of the hierarchies goes deeper than that? Also, maintaining this is going to be a nightmare. If we need to make a simple change it’s going to have to be done 10 times. Once for each nested repeat component.

Enter Dynamic Visualforce Components. Checking the documentation we find that:

Dynamic Visualforce components offer a way to create Visualforce pages that vary the content or arrangement of the component tree... dynamic Visualforce components are designed in Apex.

Rendering a Dynamic Visualforce component in a page requires the following tag:

	
    <apex:dynamicComponent componentValue=“{!thePanel}”/>

Creating a Visualforce Component in Apex can be done by referencing the Component.Apex namespace along with name of the component, e.g.

	Component.Apex.OutputField outTxt = new Component.Apex.OutputField();
	outTxt.value = rec.Name;

Creating the nested structure as Visualforce markup can be achieved by adding components to other components childComponents List, e.g.

	Component.Apex.OutputPanel outPanel = new Component.Apex.OutputPanel();
	outPanel.childComponents.add( outTxt );

If you need to add straight HTML while creating the Dynamic Visualforce Component you just use an OutputText along with the “escape=false”, e.g.

	Component.Apex.OutputText htmlTxt = new Component.Apex.OutputText();
	htmlTxt.value = ‘<h2>A Heading</h2>’;
	htmlTxt.escape = false;

If you need to bind a value to an inputText field you can update the expressions with the proper value. You will need to use the expression you would have used in the Visualforce page, e.g.

	Component.Apex.InputField inTxt = new Component.Apex.InputField(value=rec.name);
	inTxt.expressions.value = ‘{!rec.name}’;

Notice that we set value and expressions.value. The first will ensure we display the value in the input field when the page loads, the second will bind the data to the variable.

All of this means we can use Apex to dynamically create our Visualforce markup recursively and now we can iterate through our list and recreate the Visualforce structure above.

public with sharing Class Controller {
	List<WrappedRecord> myRecords = new List<WrappedRecords>();

    ... //Code to query and build myRecords and any other methods not needed for demo

    public Class WrappedRecord {
	public Record__c detail { get; set; }
	public List<WrappedRecords> children { get; set; }

	public WrappedRecord(Record__c theRecord) {
		this.detail = theRecord;
		this.children = new List<WrappedRecord>();
	}
    }
	
    public Component.Apex.OutputPanel getThePanel(){
	Component.Apex.OutputPanel outPanel = new Component.Apex.OutputPanel();
	for(Integer i=0; i<myRecords.size(); i++) {
    outPanel.childComponents.add( addChildComponents(myRecords, 0, 'myRecords') );
	}
	return outPanel;
    }

    private Component.Apex.OutputPanel addChildComponents(List<WrappedRecords> wrappers, Integer level, String accessString) {
	accessString = accessString + '[' + level + ']';
	Component.Apex.OutputPanel outPanel = new Component.Apex.OutputPanel();
	{
		Component.Apex.InputText inTxt = new Component.Apex.InputText( value = wrappers.detail.Name );
		inTxt.expressions.value = '{!' + accessString + '}';
		outPanel.childComponents.add( inTxt );
	}
	outPanel.childComponents.add( addChildComponents( wrappers.children, level+1, accessString + 'children') );

	return outPanel;
    }
}

<apex:page controller=”Controller”>
	<apex:dynamicComponent componentValue=”{!thePanel}”/>
</apex:page>

Now we have a dynamic component that calls the getThePanel method. This method creates an output panel and then iterates over the list of records adding panels with the InputText fields bound to the name of the records and recursing through the children lists. You will notice that we seed the recursive method with a counter indicating which item in the list to refer to and also pass in ‘myRecords’ as the access sting. Once the components are being recursively generated, we append ‘children’ to the access sting. This allows us to bind the inputText fields to the correct item in our list. For example we might end up with a bind string that looks like this:

    {!myRecords[2].children[3].children[1].children[0].children[2]}

which would represent the fifth level of the hierarchy.

We now have a fairly simple way to render a hierarchy of records. A call into a method which kicks off a recursive navigation of our data model will now produce the Visualforce we saw earlier in this post. We have the added benefit that a change to Visualforce will only need to be made in one place rather than at each level of Visualforce markup on the page. We also don’t have to worry about the depth of the hierarchy exceeding the depth of the static Visualforce markup.

Dynamic Visualforce components are not the preferred way to create a Visualforce page. Your code will no longer be strongly typed, meaning you may be able to delete a field without the security of the platform yelling that the field is in use.

But if you have carefully considered your situation and found that there is no good and elegant way to create your Visualforce page with static Visualforce then Dynamic Visualforce Components may work for you.

This article originally published on Developer Force, June 2013