function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
raghu123raghu123 

Creating hierarchical table

Hello Guys,

                      I need to create hierarchical table like below. from single Custom Object.Visula force page contains Four lookup fields input fields.

 

   

Warehouse             Product               Serials                Button

                        

                                Product 1             0000-1

Warehouse 1                                      0000-2      

                                Product2              0000-3  

                                                               0000-4

 

     Thaank You,

     Raghu 

Best Answer chosen by Admin (Salesforce Developers) 
Andy Freeston_LarterAndy Freeston_Larter
Sorry raghu123, my bad. The rowspan should be on the HTML TD like this:
<td rowspan=”{!wh.rowspan}"><apex:outputText value=”{!wh.warehouse.Name}”/></td>

 

 

I havn't needed to do collapsing rows yet. Thanks for the link to jQuery Grid. I'll check it out.

All Answers

r_boyd_848r_boyd_848

Not possible with anything out of the VF toolkit. If you have used jQuery I recommend looking at jqGrid http://www.trirand.com/blog/. We've used it successfully on VF pages - although not its hierarchical features.

 

The alternative is to look at may be flex of force.com and see if there is plugin for this - we've never used the flex add-in perhaps someelse in the community might know

Andy Freeston_LarterAndy Freeston_Larter

Hierarchical tables are fairly easy to do with Apex and Visualforce. You need to build a custom HTML table and style it to match the standard SFDC tables (if required).

 

You first need to build a class hierarchy in Apex that represents your data. I would guess you would have classes like this:

 

private List<WarehouseData> 		m_Warehouses;

class WarehouseData
{
	private Warehouse__c		m_Warehouse;
	List<ProductData>			m_Products;

	public Warehouse__c warehouse	{ get { return m_Warehouse; } }
	public List<ProductData> products	{ get { return m_Products; } }
	
	public Integer rowspan
	{
		Integer count = 0;
		for (ProductData pd : m_Products )
			count += pd.rowspan;
		return count;
	}
}

class ProductData
{
	private Product__c		m_Product;
	List<SerialData>		m_Serials;
	Boolean			m_IsFirst;

	public Product __c product		{ get { return m_Product; } }
	public List<SerialData> serials	{ get { return m_Serials; } }
	public Boolean isFirst		{ get { return m_IsFirst; } }

	public Integer rowspan
	{
		return m_Serials.size();
	}
}

public List<WarehouseData> warehouses
{
	get
	{
		if ( null == m_Warehouses )
		{
			// Build object hierarchy here
		}

		return m_Warehouses;
	}
}

 

There are two important pieces of information that need to be calculated. Rowspan is the number of rows that will be generated to render a given object. IsFirst is set to true for the first product or serial in the collection. You need these to correctly render the Visualforce.

 

The Visualforce page would look something like this:

 

<table>
	<tr>
		<th>Warehouse</th>
		<th>Product</th>
		<th>Serials</th>
		<th>Button </th>
	</tr>
	<apex:repeat value=”{!warehouses}” var=”wh”>
	<apex:repeat value=”{!wh.products}” var=”prod”>
	<apex:repeat value=”{!prod.serials}” var=”sr”>
	<tr>
		<apex:outputPanel layout="none" rendered="{!product.isFirst && serial.IsFirst}">
			<td><apex:outputText value=”{!wh.warehouse.Name}” rowspan=”{!wh.rowspan}"/></td>
		</apex:outputPanel>

		<apex:outputPanel layout="none" rendered="{!serial.isFirst}">
			<td><apex:outputText value=”{!prod.product.Name}” rowspan=”{!prod.rowspan}"/></td>
		</apex:outputPanel>

		<td>
			<apex:outputText value=”{!sr.serial.Name}”/>
		</td>

		<td>
			<!-- Buttons go here -->
		</td>
	</tr>
	</apex:repeat>
	</apex:repeat>
	</apex:repeat>
</table>

 

When your page loads it calls “warehouses”. You then build the object hierarchy and return your collection. The Visualforce iterates over the collection building the table one row at a time. The trick in the VF is to use rowspan in the warehouse and products columns. You only reference the warehouse and product cells once and let the rowspan do the work.

 

You can use this technique for data entry tables too. Just put set methods on your objects and have a Save method that iterates over the collection and issues insert/updates as required for new or modified values.

 

raghu123raghu123

Thank You Andy..Great Info.:))

r_boyd_848r_boyd_848

Nice one. Have you sprinkled it with javascript to allow the child rows to show/hide. We've done quite a bit with jqGrid on VF but just haven't had the need yet to use it's heirarchical features.

raghu123raghu123

Andy,

           I think there is no attribute like rowspan for <apex:outputText>

 

getting error Unsupported attribute rowspan in <apex:outputText> in SerialTransferClearBackorder

Thank You,

Raghu

Andy Freeston_LarterAndy Freeston_Larter
Sorry raghu123, my bad. The rowspan should be on the HTML TD like this:
<td rowspan=”{!wh.rowspan}"><apex:outputText value=”{!wh.warehouse.Name}”/></td>

 

 

I havn't needed to do collapsing rows yet. Thanks for the link to jQuery Grid. I'll check it out.

This was selected as the best answer