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
psplrockspsplrocks 

How to create Apex controls dynamically using Apex class.

Hi,

 

I have a VF page in which i have Apex input text controls and a command Button control.

I am able to fill the Text boxes using the properties created in the controller.

 

My requirement here is when clicked on the command button in the Vf page i want to dynamically add a input text to the VF page.

 

Can we do it using Apex code??.

 

I have been looking around for adding controls in VF page using Apex code. I went through the developers guide and cook book for reference even then i failed to get the result.

 

Do any one have an idea about adding apex controls dynamically??

Please help me out...This might be a very silly question to ask but i am not able to resolve this problem from days.

 

Thanks in Advance,

pspl 

 

 

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

If the data type is known, you can dynamically create a list (up to 1000 fields), by using a wrapper class, an array, and a apex: dataTable or apex: repeat section. Here's a simple example:

 

Controller:

 

public class pageController { public class text { public String Value { get; set; } } private List<text> textValues; public void setTextValues(List<text> items) { textValues = items; } public List<text> getTextValues() { if(textValues==null) { textValues = new List<text>(); textValues.add(new text()); } return textValues; } public void addItem() { textValues.add(new text()); } }

 Page:

<apex:page controller="pageController"> Field List: <apex:form> <apex:dataTable columns="1" value="{!textValues}" var="item"> <apex:column> <apex:inputText value="{!item.value}" /> </apex:column> </apex:dataTable><br /> <apex:commandButton action="{!addItem}" value="Add Row"/> </apex:form> </apex:page>

 

 

Since you're using a wrapper class, you could create a dynamic list of fields of any arbitrary type using "render" to display the appropriate type of field, and then modify your logic so that the correct value. My example here doesn't include picklists, but I do show how to switch between a text, textarea, and checkbox, and add and remove rows arbitrarily.

 

Controller:

 

public class pageController { public class customField { public String fieldType { get; set; } public String flagForDeletion { get; set; } private String Value; public String getTextValue() { return value; } public String getCheckValue() { return value; } public String getTextAreaValue() { return value; } public void setTextValue(String s) { value = s; } public void setCheckValue(String s) { value = s; } public void setTextAreaValue(String s) { value = s; } public Boolean getIsText() { return fieldType == 'text'; } public Boolean getIsCheck() { return fieldType == 'check'; } public Boolean getIsTextArea() { return fieldType == 'area'; } public List<SelectOption> getDataTypeList() { List<SelectOption> dataTypes = new List<SelectOption>(); dataTypes.add(new SelectOption('text','Text Field')); dataTypes.add(new SelectOption('check','Checkbox')); dataTypes.add(new SelectOption('area','Text Area')); return dataTypes; } } public List<customField> fieldList { get; set; } public pageController() { fieldList = new List<customField>(); } public void addRow() { customField cf = new customField(); cf.fieldType = 'text'; cf.flagForDeletion = 'false'; cf.setTextValue(''); fieldList.add(cf); } public void delRows() { for(Integer i = fieldList.size()-1; i>=0; i--) { if(fieldList[i].FlagForDeletion == 'true') { fieldList.remove(i); } } } }

 

 Page:

 

<apex:page controller="pageController"> Field List: <apex:form id="theForm"> <apex:dataTable columns="1" value="{!fieldList}" var="field"> <apex:column> <apex:inputCheckbox value="{!field.flagfordeletion}" /> <apex:selectList value="{!field.fieldtype}" size="1"> <apex:selectOptions value="{!field.datatypelist}" /> <apex:actionSupport event="onchange" reRender="theForm"/> </apex:selectList> <apex:inputText value="{!field.textvalue}" rendered="{!field.istext}" /> <apex:inputTextarea value="{!field.textareavalue}" rendered="{!field.istextarea}" /> <apex:inputCheckbox value="{!field.checkvalue}" rendered="{!field.ischeck}" /> </apex:column> </apex:dataTable><br /> <apex:commandButton action="{!addrow}" value="Add Row"/> <apex:commandButton action="{!delRows}" value="Delete Selected Rows"/> </apex:form> </apex:page>

 

Surely this should get you well on your way do doing whatever it is you'd like to do with your Visualforce experience. Please feel free to ask any other questions you have on this, I'll see if I can help you out.

 

 

 

All Answers

JPClarkJPClark

I don't think you can dynamically create controls, but you can programmatically hide and display controls using the render attribute. Your control button could set an apex property to true and the VF  control can use it as

render="{!displayMyControl}"

 

 

 

 

psplrockspsplrocks

Thanks for your quick reply clark. 

I exactly dont know the count of the Input controls in vf page , this count can be any number based on requirement so in this case ur solution fails it would be better if i can create controls dynamically.

is there any soln for this... 

 

 

JPClarkJPClark
Sorry, that's the best I can do. I'm rather new also.
andresperezandresperez

Hi,

 

As far as I am aware, there is no way to create dynamic controls, but something like this may do the trick for you:

 

This is the VisualForce page:

<apex:page controller="aaPage78">
 <apex:form>
  <apex:outputPanel id="out">
   <table border="1">
    <apex:repeat value="{!Lists}" var="l">
     <tr>
      <td>
       <apex:selectList value="{!l.countries}" multiselect="true">
        <apex:selectOptions value="{!l.items}"/>
       </apex:selectList><p/>
      </td>
      <td>
       <apex:actionstatus id="status" startText="testing...">
        <apex:facet name="stop">
         <apex:outputPanel>
          <p>You have selected:</p>
          <apex:dataList value="{!l.countries}" var="c">{!c}</apex:dataList>
         </apex:outputPanel>
        </apex:facet>
       </apex:actionstatus>
      </td>
     </tr>
    </apex:repeat>
   </table>
  </apex:outputPanel>
  <apex:commandButton value="Test" action="{!test}" status="status"/>
 </apex:form>
</apex:page>

 

And this is the Controller:

 

public class aaPage78 {
 public List<selectList> lists {get; set;}

 public aaPage78() {
  lists = new List<selectList>();
  for (Integer i = 0; i < 5; i++) {
   lists.add(new selectList(i));
  }
 }

 public PageReference test() {
  return null;
 }

 public class selectList {
  Integer intValue;
  String[] countries = new String[]{};

  public selectList(Integer intValue) {
   this.intValue = intValue;
  }
  public List<SelectOption> getItems() {
   List<SelectOption> options = new List<SelectOption>();
   options.add(new SelectOption('Value:' + intValue + ' - US','Label:' + intValue + ' - US'));
   options.add(new SelectOption('Value:' + intValue + ' - CANADA','Label:' + intValue + ' - Canada'));
   options.add(new SelectOption('Value:' + intValue + ' - MEXICO','Label:' + intValue + ' - Mexico'));
   return options;
  }

  public String[] getCountries() {
   return countries;
  }

  public void setCountries(String[] countries) {
   this.countries = countries;
  }

 }
}

In here I am creating 5 listboxes, but you can easily get the idea.

 

One thing to know, is that creating "custom" code is harder than "regular" code

sfdcfoxsfdcfox

If the data type is known, you can dynamically create a list (up to 1000 fields), by using a wrapper class, an array, and a apex: dataTable or apex: repeat section. Here's a simple example:

 

Controller:

 

public class pageController { public class text { public String Value { get; set; } } private List<text> textValues; public void setTextValues(List<text> items) { textValues = items; } public List<text> getTextValues() { if(textValues==null) { textValues = new List<text>(); textValues.add(new text()); } return textValues; } public void addItem() { textValues.add(new text()); } }

 Page:

<apex:page controller="pageController"> Field List: <apex:form> <apex:dataTable columns="1" value="{!textValues}" var="item"> <apex:column> <apex:inputText value="{!item.value}" /> </apex:column> </apex:dataTable><br /> <apex:commandButton action="{!addItem}" value="Add Row"/> </apex:form> </apex:page>

 

 

Since you're using a wrapper class, you could create a dynamic list of fields of any arbitrary type using "render" to display the appropriate type of field, and then modify your logic so that the correct value. My example here doesn't include picklists, but I do show how to switch between a text, textarea, and checkbox, and add and remove rows arbitrarily.

 

Controller:

 

public class pageController { public class customField { public String fieldType { get; set; } public String flagForDeletion { get; set; } private String Value; public String getTextValue() { return value; } public String getCheckValue() { return value; } public String getTextAreaValue() { return value; } public void setTextValue(String s) { value = s; } public void setCheckValue(String s) { value = s; } public void setTextAreaValue(String s) { value = s; } public Boolean getIsText() { return fieldType == 'text'; } public Boolean getIsCheck() { return fieldType == 'check'; } public Boolean getIsTextArea() { return fieldType == 'area'; } public List<SelectOption> getDataTypeList() { List<SelectOption> dataTypes = new List<SelectOption>(); dataTypes.add(new SelectOption('text','Text Field')); dataTypes.add(new SelectOption('check','Checkbox')); dataTypes.add(new SelectOption('area','Text Area')); return dataTypes; } } public List<customField> fieldList { get; set; } public pageController() { fieldList = new List<customField>(); } public void addRow() { customField cf = new customField(); cf.fieldType = 'text'; cf.flagForDeletion = 'false'; cf.setTextValue(''); fieldList.add(cf); } public void delRows() { for(Integer i = fieldList.size()-1; i>=0; i--) { if(fieldList[i].FlagForDeletion == 'true') { fieldList.remove(i); } } } }

 

 Page:

 

<apex:page controller="pageController"> Field List: <apex:form id="theForm"> <apex:dataTable columns="1" value="{!fieldList}" var="field"> <apex:column> <apex:inputCheckbox value="{!field.flagfordeletion}" /> <apex:selectList value="{!field.fieldtype}" size="1"> <apex:selectOptions value="{!field.datatypelist}" /> <apex:actionSupport event="onchange" reRender="theForm"/> </apex:selectList> <apex:inputText value="{!field.textvalue}" rendered="{!field.istext}" /> <apex:inputTextarea value="{!field.textareavalue}" rendered="{!field.istextarea}" /> <apex:inputCheckbox value="{!field.checkvalue}" rendered="{!field.ischeck}" /> </apex:column> </apex:dataTable><br /> <apex:commandButton action="{!addrow}" value="Add Row"/> <apex:commandButton action="{!delRows}" value="Delete Selected Rows"/> </apex:form> </apex:page>

 

Surely this should get you well on your way do doing whatever it is you'd like to do with your Visualforce experience. Please feel free to ask any other questions you have on this, I'll see if I can help you out.

 

 

 

This was selected as the best answer
splitsplit
Thank you very much for this! :smileyhappy:
bcgbcg

Hi there,

 

It is very interesting thing , but do you know how to save all the records in this page.

If you have any idae then please post.

 

 

 

Thanks

sfdcfoxsfdcfox

@bcg:

 

Looking at this example, I realize it's not necessarily the best I could have come up with. However, all that is really needed is to loop through the fieldList list and perform some action on the results. Regrettably, the prior code lacks an ID value or Name to work with, so it becomes cumbersome. However, if you added the ability to track the field name, and changed Value to a public-access variable, you would do the following:

 

 

public ApexPage.pageReference saveRecord() {
  Sobject obj = new Sobject('Account');
  for(customField field:fieldList) {
    obj.put(field.fieldName,field.Value);
  }
  Database.upsert(obj);
  return obj.view();
}

 

 

Please let me know if you need further clarification.

 

Thanks!

PRASHANT SOAMPRASHANT SOAM

How can we post back data from dynamically created textboxes. Like if we have created 4 textboxes then how do we post back data from those textboxes to controller we we are not certain about no of textboxes.

sfdcfoxsfdcfox

If you used my previous example, they'd be bound to the collection of data. The text boxes are just UI elements, but they are bound to real values. Make sure that the "value" attribute is a formula (e.g. {!object.fieldname} ) and not just a copy of the text (e.g. component.value = object.fieldname ).

andresperezandresperez

Have you taken a look at "Dynamic Visualforce Components"? There is a much easier way to do this now. Check it out: 

 

 

 

Dynamic Visualforce Components