3

I am designing a custom input picklist form that will be data-driven.Based on picklist value selected next question should show up with the picklist options.Like wise it might end up having 10-15 Picklist Questions based on the pathway choosen.

So am trying to create selectlist with options dynamically

How to show questions with picklist options created dynamically on visualforce page

Current Application Details:

We currently have visualforce wizard with questions and picklist options and our client didn't liked it i.e clicking on next or previous buttons for 15 times or more depending on the pathway the user selected ...we are trying to propose it with single page application like with on change of picklist value show related question with picklist options

Any help is appreciated .

Here is part of class and page

Class

    public Component.Apex.OutputPanel getThePanel2(){
           Component.Apex.OutputPanel outPanel1 = new Component.Apex.OutputPanel();
           outPanel1 = getcurrentPanel2();
           return outPanel1 ;
        } 

  public boolean showDynamic{get;set;}

  public Component.Apex.OutputPanel getcurrentPanel2(){

     Component.Apex.OutputPanel outPanel1 = new Component.Apex.OutputPanel();
     outPanel1.id='currentsect';

     Component.Apex.SelectList STQPicklist = new Component.Apex.SelectList();
     STQPicklist.StyleClass = 'form-control';
     STQPicklist.StyleClass = 'col-md-4';
     STQPicklist.Size = 1;


     Component.Apex.ActionSupport asu = new Component.Apex.ActionSupport (event='onchange');         
     asu.expressions.action='{!getNextChild}';
      set<string> outputPanelId = new set<string>();
     outputPanelId.add('WizardQues3');
     asu.rerender=outputPanelId;

     Component.Apex.selectOptions STQOptions = new Component.Apex.SelectOptions();
     STQOptions.expressions.value = '{!progLineItemPathwayItems}';


     STQPicklist.childComponents.add(STQOptions);
     STQPicklist.childComponents.add(asu);


      Component.Apex.Outputlabel outlab= new Component.Apex.Outputlabel();
      outlab.value = 'What do you want to Import';
      outlab.StyleClass = 'col-md-4';

          outPanel1.childComponents.add(outlab);
          outPanel1.childComponents.add(STQPicklist);

          return outPanel1;
    }

Page

<apex:outputPanel id="WizardQues2">
     <apex:outputPanel rendered="{!if(showDynamic = true,true,false)}">
     <div class="row" style="margin-bottom:15px;" >
    <apex:dynamicComponent componentValue="{!thePanel2}" id="dyncompt"/>
     </div>
    </apex:outputPanel>
  </apex:outputPanel>
 <apex:outputPanel id="WizardQues3">
     <apex:outputPanel rendered="{!if(showDynamic = true,true,false)}">
     <div class="row" style="margin-bottom:15px;" >
  <apex:dynamicComponent componentValue="{!thePanel2}" id="dyncompt"/>
  </div>
  </apex:outputPanel>
</apex:outputPanel>
2
  • hey sfdc .. Just remove asu.rerender=outputPanelId; this will work.. I think issue with you are passing wrong Id in rerender .. I suggest just remove asu.rerender=outputPanelId; and try..
    – Ratan Paul
    Mar 3, 2016 at 16:45
  • Also you can use rerender you need to pass output panel Id outPanel1.id='currentsect'; in list of string ` set<string> outputPanelId = new set<string>{'currentsect'};` and finally add asu.rerender=outputPanelId; ... this way it will work
    – Ratan Paul
    Mar 3, 2016 at 16:55

2 Answers 2

2

So basically issue in your ActionSupport attribute rerender

Currently in your code

set<string> outputPanelId = new set<string>();
asu.rerender=outputPanelId;

You are not passing Id. You can remove this line asu.rerender=outputPanelId; OR you can pass the ouputPanel Id..

In above code you have created outputPanel i.e.

Component.Apex.OutputPanel outPanel1 = new Component.Apex.OutputPanel();
outPanel1.id='currentsect';

So we can assign this Id currentsect to rerender attribute

set<string> outputPanelId = new set<string>{'currentsect'};
asu.rerender=outputPanelId;

This way it will work...


Updates

Dynamic dependent picklist one level

VF Page

<apex:page controller="dynamicPicklist">
    <apex:form id="frm"><apex:pageBlock >
  <apex:dynamicComponent componentValue="{!ThePanel2}"/>
  <apex:dynamicComponent componentValue="{!currentPanel2Child}"/>
  </apex:pageBlock>
  </apex:form>
</apex:page>

Controller

public class dynamicPicklist {
    public List<SelectOption> progLineItemPathwayItems {get;set;}
    public List<String> lstSelectedprogLineItemPathwayItems {get;set;}

    public List<SelectOption> progLineItemPathwayChildItems {get;set;}
    public boolean showDynamic{get;set;}
    public String strSelected1 {get;set;}
    private map<String, List<String>> mapStringtoLstString;
    public dynamicPicklist(){

        showDynamic = false;
        strSelected1 = '';
        mapStringtoLstString = new map<String, List<String>>();
        lstSelectedprogLineItemPathwayItems = new List<String>();
        mapStringtoLstString.put('First1', new List<String>{'First1-1','First1-2', 'First1-3'});
        mapStringtoLstString.put('First2', new List<String>{'First2-1','First2-2', 'First2-3'});
        mapStringtoLstString.put('First3', new List<String>{'First3-1','First3-2', 'First3-3'});

        progLineItemPathwayItems = new List<SelectOption>();
        progLineItemPathwayChildItems = new List<SelectOption>();
        progLineItemPathwayItems.add(new SelectOption('First1', 'First1'));
        progLineItemPathwayItems.add(new SelectOption('First2', 'First2'));
        progLineItemPathwayItems.add(new SelectOption('First3', 'First3'));

    }

    public void getNextChild(){
       if(String.isNotBlank(strSelected1))
         showDynamic =true;
    }
   public Component.Apex.OutputPanel getThePanel2(){
           Component.Apex.OutputPanel outPanel1 = new Component.Apex.OutputPanel();
           outPanel1 = getcurrentPanel2();
           return outPanel1 ;
    } 
   public Component.Apex.OutputPanel getcurrentPanel2Child(){

     Component.Apex.OutputPanel outPanel1 = new Component.Apex.OutputPanel();
     outPanel1.rendered = showDynamic;
     outPanel1.id='currentsect1';

     Component.Apex.SelectList STQPicklist = new Component.Apex.SelectList();
     STQPicklist.StyleClass = 'form-control';
     STQPicklist.StyleClass = 'col-md-4';
     STQPicklist.Size = 1;
     STQPicklist.value = lstSelectedprogLineItemPathwayItems;

     Component.Apex.ActionSupport asu = new Component.Apex.ActionSupport ();
     asu.event = 'onchange';
     asu.expressions.action='{!getNextChild}';
      set<string> outputPanelId = new set<string>{'currentsect1'};
     outputPanelId.add('WizardQues3');
     asu.rerender=outputPanelId;
     progLineItemPathwayChildItems = new List<SelectOption>();

     progLineItemPathwayChildItems.add(new SelectOption('', '--None--'));   
      if(String.isNotBlank(strSelected1)){
        for(String str: mapStringtoLstString.get(strSelected1))
        {
            progLineItemPathwayChildItems.add(new SelectOption(str, str));
        }
      }

     Component.Apex.selectOptions STQOptions = new Component.Apex.SelectOptions();
     STQOptions.expressions.value = '{!progLineItemPathwayChildItems}';


     STQPicklist.childComponents.add(STQOptions);
     STQPicklist.childComponents.add(asu);


      Component.Apex.Outputlabel outlab= new Component.Apex.Outputlabel();
      outlab.value = 'What do you want to Import';
      outlab.StyleClass = 'col-md-4';

      outPanel1.childComponents.add(outlab);
      outPanel1.childComponents.add(STQPicklist);

      return outPanel1;
    }


  public Component.Apex.OutputPanel getcurrentPanel2(){

     Component.Apex.OutputPanel outPanel1 = new Component.Apex.OutputPanel();
     outPanel1.id='currentsect';

     Component.Apex.SelectList STQPicklist = new Component.Apex.SelectList();
     STQPicklist.StyleClass = 'form-control';
     STQPicklist.StyleClass = 'col-md-4';
     STQPicklist.Size = 1;
     STQPicklist.multiselect = false;
     STQPicklist.expressions.value = '{!strSelected1}';

     Component.Apex.ActionSupport asu = new Component.Apex.ActionSupport ();
     asu.event = 'onchange';
     asu.expressions.action='{!getNextChild}';
      set<string> outputPanelId = new set<string>{'frm'};
     outputPanelId.add('WizardQues3');
     asu.rerender=outputPanelId;

     Component.Apex.selectOptions STQOptions = new Component.Apex.SelectOptions();
     STQOptions.expressions.value = '{!progLineItemPathwayItems}';


     STQPicklist.childComponents.add(STQOptions);
     STQPicklist.childComponents.add(asu);


      Component.Apex.Outputlabel outlab= new Component.Apex.Outputlabel();
      outlab.value = 'What do you want to Import';
      outlab.StyleClass = 'col-md-4';

      outPanel1.childComponents.add(outlab);
      outPanel1.childComponents.add(STQPicklist);

      return outPanel1;
    }
}
7
  • Thanks Ratan but how should I create new picklist question (dynamic component) based on selected picklist value?
    – sfdc
    Mar 3, 2016 at 21:03
  • @sfdc This is really a broad question.. but np, I have updated Ans with example for one level dependent picklist..... You need to make this code optimize and reusable since you have to use 10-15 picklist so good luck for that..
    – Ratan Paul
    Mar 4, 2016 at 2:36
  • @sfdc Can you tell what you are looking for now. Let me know if I can help with that..
    – Ratan Paul
    Mar 5, 2016 at 3:55
  • We currently have visualforce wizard with questions and picklist options and our client didn't liked it i.e clicking on next or previous buttons for 15 times or more depending on the pathway the user selected ...we are trying to propose it with single page application like with on change of picklist value show related question.
    – sfdc
    Mar 5, 2016 at 4:13
  • @sfdc I feel like above my example is same thing if you select one option, another will display, both are in same page.. is it same what you are looking for?
    – Ratan Paul
    Mar 5, 2016 at 4:25
0

A re-render is typically quite sluggish which can be a little frustrating and sometimes confusing for the user. (Perhaps the slowness of the wizard approach is contributing to your client's dislike.) I suggest that the best user experience would come from keeping as much of the logic as possible at the client-side so that when a selection is made in one picklist the next picklist comes up instantly.

Whether that can be accomplished depends on how the picklists are related: if it is a fixed relationship then the values can be modelled in say some JSON kept in a static resource. The UI would then be primarily JavaScript with say jQuery, with the final results passed back to the server at the end of the process via say JavaScript remoting.

The other obvious problem is that most of the work would be in JavaScript and so would require strong JavaScript skills and also HTML and CSS skills. To give some sense of the sort of code involved, this code creates picklists (HTML select elements) based on some JSON:

<apex:page>

<apex:pageBlock>
    <apex:pageBlockSection>
        <table id="table"/>
    </apex:pageBlockSection>
</apex:pageBlock>

<script src="https://code.jquery.com/jquery-1.12.1.min.js"/>

<script>

(function($) {

    // This JSON would come from e.g. a static resource and include
    // additional attributes to model the dependencies and jQuery would
    // be used to update the page when a select list changes
    var items = [
        {
            "id": "first",
            "label": "First",
            "options": ["a", "b", "c"]
        },
        {
            "id": "second",
            "label": "Second",
            "options": ["x", "y", "z"]
        }
    ];

    $(document).ready(function() {

        var table = $('#table');
        for (var i = 0; i < items.length; i++) {
            var item = items[i];
            var options = '';
            for (var j = 0; j < item.options.length; j++) {
                options += ''
                        + '<option value="' + item.options[j] + '">'
                        + item.options[j]
                        + '</option>'
                        ;
            }
            var html = ''
                     + '<tr><td>'
                     + '<label for="' + item.id + '">' + item.label + '</label>'
                     + '</td><td>'
                     + '<select id="' + + item.id + '">'
                     + options
                     + '</select>'
                     + '</td></tr>'
                     ;
            table.append(html);
        }
    });
})(jQuery.noConflict());

</script>
</apex:page>

You must log in to answer this question.

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