I would like to be able to dynamically control the columns displayed in a page block table. This would mean that if new fields are added to the object the controller and page do not have to be updated.
I understand that a standard list view could used, be the data model is:
Parent_c -< Child_c -< Grandchild__c
And I will be building a page displaying all the grandchildren for a selected Parent, and creating a list view for each parent is not ideal.
Attribution to: Daniel Blackhall
Possible Suggestion/Solution #1
You could using Dynamic Visualforce Components to construct the pageBlockTable, which avoids the limitation re headings when adding columns dynamically in VF alone.
Controller:
public List<Account> getAccountList()
{
String fieldList = '';
for(Schema.FieldSetMember fsm : SObjectType.Account.FieldSets.MyFieldset.getFields())
fieldList += fieldList.length()>0 ? ','+fsm.getFieldPath() : fsm.getFieldPath();
return (List<Account>) Database.query('select ' + fieldList + ' from Account');
}
public Component.Apex.PageBlockTable getMyPageBlockTable()
{
Component.Apex.PageBlockTable table = new Component.Apex.PageBlockTable(var='acc');
table.expressions.value='{!AccountList}';
for(Schema.FieldSetMember fsm : SObjectType.Account.FieldSets.MyFieldset.getFields())
{
Component.Apex.OutputField outputField = new Component.Apex.OutputField();
outputField.expressions.value = '{!acc.' + fsm.getFieldPath() + '}';
Component.Apex.Column column = new Component.Apex.Column(headerValue=fsm.getLabel());
column.childComponents.add(outputField);
table.childComponents.add(column);
}
return table;
}
Visualforce page:
<apex:pageBlock >
<apex:dynamicComponent componentValue="{!MyPageBlockTable}"/>
</apex:pageBlock>
Attribution to: Stephen Willcock
Possible Suggestion/Solution #2
Page Block Tables actually support <apex:repeat>
tags (This was not originally supported). The following example demonstrates 2 ways of accomplishing dynamic columns in a table depending on the type of data you supply.
Using fieldsets is the simplest way to control dynamic columns. This is the best choice if displaying a table of SObjects
<apex:pageBlock id="block">
<apex:pageBlockTable id="table" var="account" value="{!accounts}">
<apex:column headerValue="Account Name" value="{!account.Name}" />
<apex:repeat var="f" value="{!$ObjectType.Account.FieldSets.Example_Fieldset}">
<apex:column headerValue="{!f.label}">
<apex:inputField value="{!account[f]}" />
</apex:column>
</apex:repeat>
</apex:pageBlockTable>
</apex:pageBlock>
If you are using a List, there is an important gotcha with dynamic tables: header cells are not rendered. The fix is to declare the following css snippet and apply the style as outlined below
<style type="text/css">
.empty-column-content {
display: none;
}
</style>
<apex:pageBlock id="block2">
<apex:pageBlockTable id="table" var="row" value="{!rows}">
<apex:repeat var="cell" value="{!row.cells}">
<apex:column headerValue="No matter how this is defined, it results in an empty cell">
<apex:outputText value="{!cell}" />
</apex:column>
</apex:repeat>
<!--Define the headers here and hide the empty cells that are created -->
<apex:repeat var="header" value="{!headers}">
<apex:column headerValue="{!header}" styleClass="empty-column-content" />
</apex:repeat>
</apex:pageBlockTable>
</apex:pageBlock>
The example controller for the visualforce snippets above:
public with sharing class PageBlockTableFieldSetExample {
public List<Account> accounts { get; private set; }
public List<String> headers { get; private set; }
public List<RowExample> rows { get; private set; }
public PageBlockTableFieldSetExample() {
String queryFields = '';
for(Schema.FieldSetMember f : SObjectType.Account.FieldSets.Example_Fieldset.getFields()) {
if(queryFields.length() > 0) {
queryFields += ', ';
}
queryFields += f.getFieldPath();
}
//Query the records you want to display
this.accounts = Database.query(
' SELECT ' +
queryFields +
' FROM ' +
' Account ' +
' WHERE ' +
' AccountNumber = null ' +
' LIMIT 10 ');
//Setup the row of classes example
this.headers = new List<String> { 'Monday', 'Tuesday', 'Wednesday' };
this.rows = new List<RowExample>();
for(Integer i = 0; i < 3; i++) {
this.rows.add(new RowExample(this.headers.size()));
}
}
public class RowExample {
//A variable number of cells in different rows will result in
public final List<String> cells { get; private set; }
public RowExample(Integer length) {
this.cells = new List<String>();
for(Integer i = 0; i < 3; i++) {
this.cells.add('Cell ' + (math.random() * 10).intValue());
}
}
}
}
Attribution to: Daniel Blackhall
This content is remixed from stackoverflow or stackexchange. Please visit https://salesforce.stackexchange.com/questions/245