2

Is it possible to dynamically create a form using data to control the types of input fields on the form using APEX/VisualForce and/or Javascript interop? In ASP.NET I'd programmatically add controls to the Page's controls collection. Those controls could be containers (containing input controls) or they could be input controls, either way, when the page renders, the page just renders the control tree, and the controls would appear grouped, ordered and of the correct type as if they had been hard coded in the ASPX page.

For example, given this data:

Id,Group,Caption,FieldType
1,Licence Details,Version Required,TextBox
2,Licence Details,Customer ID,TextBox
3,Licence Details,Expiry Date,DatePicker
4,Product Options,Alerts,Checkbox
5,Product Options,Video,Checkbox
6,Product Options,Poll,Checkbox

I'd want to create a pageBlockSection object titled 'Licence Details', containing 2 inputText objects, a date input and so on.

The apex:repeater seems to render the same 'template' for each data item; what I want to do is render a different template based on the last field of the data.

If this can't be done in APEX, might this be possible by building the form in the client using salesforce/Javascript interop and something equivalent to a 'page method' to receive a form post or ajax post triggered without a full page postback.

1 Answer 1

3

You can do this with Dynamic Visualforce Components. Basically you construct (part of) the page out of components you generate in an APEX class. You'd loop through the items in your list and create Components accordingly.

Below a standard example (taken from https://www.salesforce.com/us/developer/docs/pages/Content/pages_dynamic_vf_components_implementation.htm):

You'd have to add or not add the child components based on your page definitions.

VF page:

<apex:form>
    <apex:dynamicComponent componentValue="{!dynamicForm}"/>
</apex:form>

APEX controller:

public Component.Apex.PageBlock getDynamicForm() {
    Component.Apex.PageBlock dynPageBlock = new Component.Apex.PageBlock();

    // Create an input field for Account Name
    Component.Apex.InputField theNameField = new Component.Apex.InputField();
    theNameField.expressions.value = '{!Account.Name}';
    theNameField.id = 'theName';
    Component.Apex.OutputLabel theNameLabel = new Component.Apex.OutputLabel();
    theNameLabel.value = 'Rename Account?';
    theNameLabel.for = 'theName';

    // Create an input field for Account Number
    Component.Apex.InputField theAccountNumberField = new Component.Apex.InputField();
    theAccountNumberField.expressions.value = '{!Account.AccountNumber}';
    theAccountNumberField.id = 'theAccountNumber';
    Component.Apex.OutputLabel theAccountNumberLabel = new Component.Apex.OutputLabel();
    theAccountNumberLabel.value = 'Change Account #?';
    theAccountNumberLabel.for = 'theAccountNumber';

    // Create a button to submit the form
    Component.Apex.CommandButton saveButton = new Component.Apex.CommandButton();
    saveButton.value = 'Save';
    saveButton.expressions.action = '{!Save}';

    // Assemble the form components
    dynPageBlock.childComponents.add(theNameLabel);
    dynPageBlock.childComponents.add(theNameField);
    dynPageBlock.childComponents.add(theAccountNumberLabel);
    dynPageBlock.childComponents.add(theAccountNumberField);
    dynPageBlock.childComponents.add(saveButton);

    return dynPageBlock;
}
2
  • That's pretty much what I've had to do however, a new problem has arisen: How to I access the control tree on Save? The save method fires, but I need to walk the control tree to pull out form field values. Or is their another way?
    – IanT8
    Jun 22, 2014 at 23:40
  • The field values will be assigned automatically to the variables put in the 'value' attribute. E.g. the example is based on a page using the Account standardcontroller, which is why the {!Account.AccountNumber} will be assigned to the Account that is in scope. The {!Save} action will then use the standard save method and update the Account. Alternatively, if you don't use a standardcontroller, replace the {!Account.AccountNumber} by {!yourRecordVariable.yourField} and implement a custom save method that updates yourRecordVariable. Jun 23, 2014 at 9:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .