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
Aryan05Aryan05 

Need help, anyone can explain me the error from the below please.

Visualforce Page 1: 
<apex:page standardController="Account" recordSetVar="accountList"
           extensions="DynamicCustomizableListHandler">
    <br/>
    <apex:form >

    <!-- View selection widget, uses StandardController methods -->
    <apex:pageBlock >
        <apex:outputLabel value="Select Account Views: " for="viewsList"/>
        <apex:selectList id="viewsList" size="1" value="{!filterId}">
            <apex:actionSupport event="onchange" rerender="theTable"/>
            <apex:selectOptions value="{!listViewOptions}"/>
        </apex:selectList>
    </apex:pageblock>

    <!-- This list of accounts has customizable columns -->
    <apex:pageBlock title="Accounts" mode="edit">
        <apex:pageMessages />
        <apex:panelGroup id="theTable">
            <apex:pageBlockTable value="{!accountList}" var="acct">
                <apex:column value="{!acct.Name}"/>
                <!-- This is the dynamic reference part -->
                <apex:repeat value="{!displayFields}" var="f">
                    <apex:column value="{!acct[f]}"/>
                </apex:repeat>
            </apex:pageBlockTable>
        </apex:panelGroup>
    </apex:pageBlock>

    <br/>
    <apex:commandButton value="Customize List" action="{!customize}"/>

    </apex:form>
</apex:page>

Apex Class:
public class DynamicCustomizableListHandler {

    // Resources we need to hold on to across requests
    private ApexPages.StandardSetController controllerr;
    private PageReference savePage;

    // This is the state for the list "app"
    private Set<String> unSelectedNames = new Set<String>();
    private Set<String> selectedNames = new Set<String>();
    private Set<String> inaccessibleNames = new Set<String>();

    public DynamicCustomizableListHandler(ApexPages.StandardSetController controller) {
        this.controllerr = controller;
        loadFieldsWithVisibility();
    }

    // Initial load of the fields lists
    private void loadFieldsWithVisibility() {
        Map<String, Schema.SobjectField> fields = 
            Schema.SobjectType.Account.fields.getMap();
        for (String s : fields.keySet()) {
            if (s != 'Name') {  // name is always displayed 
                unSelectedNames.add(s);
            }
            if (!fields.get(s).getDescribe().isAccessible()) {
                inaccessibleNames.add(s);
            }
        }
    }

    // The fields to show in the list
    // This is what we generate the dynamic references from
    public List<String> getDisplayFields() { 
        List<String> displayFields = new List<String>(selectedNames);
        displayFields.sort();
        return displayFields;
    }
    
    // Nav: go to customize screen
    public PageReference customize() {
        savePage = ApexPages.currentPage();
        return Page.CustomizeDynamicList;
    }

    // Nav: return to list view
    public PageReference show() {
        // This forces a re-query with the new fields list
        controllerr.reset();
        controllerr.addFields(getDisplayFields());
        return savePage; 
    }

    // Create the select options for the two select lists on the page
    public List<SelectOption> getSelectedOptions() { 
        return selectOptionsFromSet(selectedNames);
    }
    public List<SelectOption> getUnSelectedOptions() { 
        return selectOptionsFromSet(unSelectedNames);
    }
    
    private List<SelectOption> selectOptionsFromSet(Set<String> opts) {
        List<String> optionsList = new List<String>(opts);
        optionsList.sort();
        List<SelectOption> options = new List<SelectOption>();
        for (String s : optionsList) {
            options.add(new 
                SelectOption(s, decorateName(s), inaccessibleNames.contains(s)));
        }
        return options;
    }

    private String decorateName(String s) {
        return inaccessibleNames.contains(s) ? '*' + s : s;
    }

    // These properties receive the customization form postback data
    // Each time the [<<] or [>>] button is clicked, these get the contents
    // of the respective selection lists from the form
    public transient List<String> selected   { get; set; }
    public transient List<String> unselected { get; set; }

    // Handle the actual button clicks. Page gets updated via a
    // rerender on the form
    public void doAdd() {
        moveFields(selected, selectedNames, unSelectedNames);
    }
    public void doRemove() {
        moveFields(unselected, unSelectedNames, selectedNames);
    }
    
    private void moveFields(List<String> items, 
            Set<String> moveTo, Set<String> removeFrom) {
        for (String s: items) {
            if( ! inaccessibleNames.contains(s)) {
                moveTo.add(s);
                removeFrom.remove(s);
            }
        }
    }
}

Visualforce Page 2: 
<apex:page standardController="Account" recordSetVar="ignored"
           extensions="DynamicCustomizableListHandler">
    <br/>
    <apex:form >

    <apex:pageBlock title="Select Fields to Display" id="selectionBlock">
        <apex:pageMessages />
        <apex:panelGrid columns="3">
            <apex:selectList id="unselected_list" required="false" 
                value="{!selected}" multiselect="true" size="20" style="width:250px">
                <apex:selectOptions value="{!unSelectedOptions}"/>
            </apex:selectList>
            <apex:panelGroup >
                <apex:commandButton value=">>" 
                    action="{!doAdd}" rerender="selectionBlock"/>
                <br/>
                <apex:commandButton value="<<" 
                    action="{!doRemove}" rerender="selectionBlock"/>
            </apex:panelGroup>
            <apex:selectList id="selected_list" required="false" 
                value="{!unselected}" multiselect="true" size="20" style="width:250px">
                <apex:selectOptions value="{!selectedOptions}"/>
            </apex:selectList>
        </apex:panelGrid>
        <em>Note: Fields marked <strong>*</strong> are inaccessible to your account</em>
    </apex:pageBlock>
    
    <br/>
    <apex:commandButton value="Show These Fields" action="{!show}"/>

    </apex:form>

</apex:page>

------------------------- The above code is working fine and the below code is not woking as expected, both are same code ----------------------
Anyone can expalin what's the mistake. And i'm getting the error as "System.SObjectException: SObject row was retrieved via SOQL without querying the requested field"

Visualforce Page 
<apex:page standardController="Account" recordSetVar="accountList" extensions="DynamicCustomizableListHandler"> <br />
  
  <apex:form >
      <!-- View selection widget, uses StandaredController method  -->
      <apex:pageBlock >
          <apex:outputLabel value="Select Account Views: " for="viewList"/>
          <apex:selectList id="viewList" size="1" value="{!filterId}">
              <apex:actionSupport event="onchange" reRender="theTable"/>
              <apex:selectOptions value="{!listViewOptions}"/>
          </apex:selectList>
      </apex:pageBlock>
      
      <!-- This list of accounts has customizable coloumns -->
      <apex:pageBlock title="Accounts" mode="edit">
          <apex:pageMessages />
          <apex:panelGroup id="theTable">
              <apex:pageBlockTable value="{!accountList}" var="acct">
                  <apex:column value="{!acct.Name}"/>
                  <!-- This is dynamic reference part -->
                  <apex:repeat value="{!displayFields}" var="f">
                      <apex:column value="{!acct[f]}"/>
                  </apex:repeat>
              </apex:pageBlockTable>
          </apex:panelGroup>
      </apex:pageBlock>
      <br />
      <apex:commandButton value="Customize List" action="{!customize}"/>
  </apex:form>
</apex:page>

Apex Class
public class DynamicCustomizableListHandler {

    // Resources we need to hold on to across requests
    private ApexPages.StandardSetController controllerr;
    private PageReference savePage;
    
    // This is the stage for the list "app"
    private Set<String> unSelectedNames = new Set<String>();
    private Set<String> selectedNames = new Set<String>();
    private Set<String> inaccessibleNames = new Set<String>();
    
    public DynamicCustomizableListHandler(ApexPages.StandardSetController controller) {
        this.controllerr = controller;
        loadFieldsWithVisibility();
    }
    
    // Initial load of the fields list
    private void loadFieldsWithVisibility() {
        Map<String, Schema.SobjectField> fields = Schema.SobjectType.Account.fields.getMap();
        for(String s : fields.keySet()) {
            if(s != 'Name') { // name is always display
                unSelectedNames.add(s);
            }
            if(!fields.get(s).getDescribe().isAccessible()) {
                inaccessibleNames.add(s);
            }
        }
    }
    
    // The fields to show in the list
    // This is what we generate the dynamic reference from
    public List<String> getDisplayFields() {
        List<String> displayFields = new List<String>(selectedNames);
        displayFields.sort();
        return displayFields;
    }
    
    // Nav: go to customize screen
    public PageReference customize() {
        savePage = ApexPages.currentPage();
        return Page.CustomizeDynamicList;
    }
    
    // Nav: return to list view
    public PageReference show() {
        // This force a re-query with the new field list
        controllerr.reset();
        controllerr.addFields(getDisplayFields());
        return savePage;
    }
    
    // Create the select options for the two select lists on the page
    public List<SelectOption> getSelectedOptions() {
        return selectOptionsFromSet(selectedNames);
    }
    
    public List<SelectOption> getUnSelectedOptions() {
        return selectOptionsFromSet(unSelectedNames);
    }
    
    private List<SelectOption> selectOptionsFromSet(Set<String> opts) {
        List<String> optionsList = new List<String>(opts);
        optionsList.sort();
        List<SelectOption> options = new List<SelectOption>();
        for(String s : optionsList) {
            options.add(new SelectOption(s, decorateName(s), inaccessibleNames.contains(s)));
        }
        return options;
    }
    
    private String decorateName(String s) {
        return inaccessibleNames.contains(s) ? '*' + s : s;
    }
    
    // These properties receive the customization from postback data
    // Each time the [<<] or [>>] button are clicked, these get the contents of the respective selection lists from the form
    public transient List<String> selected { get; set; }
    public transient List<String> unselected { get; set; }
    
    // Handle the actual button clicks, Page gets updated via a rerender a form
    public void doAdd() {
        moveFields(selected, selectedNames, unSelectedNames);
    }
    
    public void doRemove() {
        moveFields(unselected, unSelectedNames, selectedNames);
    }
    
    private void moveFields(List<String> items, Set<String> moveTo, Set<String> removeFrom) {
        for(String s : items) {
            if(! inaccessibleNames.contains(s)) {
                moveTo.add(s);
                removeFrom.remove(s);
            }   
        }
    }
}

Visualforce Page
<apex:page standardController="Account" recordSetVar="ignored" extensions="DynamicCustomizableListHandler">
  <br />
  <apex:form >
      <apex:pageBlock title="Select Fields To Display" id="selectionBlock">
          <apex:pageMessages />
          <apex:panelGrid columns="3">
              <apex:selectList id="unselected_list" required="false" value="{!selected}" multiselect="true" size="20" style="width:250px">
                  <apex:selectOptions value="{!unSelectedOptions}"/>
              </apex:selectList>
              <apex:panelGroup >
                  <apex:commandButton value=">>" action="{!doAdd}" rerender="selectionBlock"/>
                  <br />
                  <apex:commandButton value="<<" action="{!doRemove}" reRender="selectionBlock"/>
              </apex:panelGroup>
              <apex:selectList id="selected_list" required="false" value="{!unselected}" multiselect="true" size="20" style="width:250px">
                  <apex:selectOptions value="{!SelectedOptions}"/>
              </apex:selectList>
          </apex:panelGrid>
          <em>Note: Fields marked <strong>*</strong> are inaccessible to your account</em>
      </apex:pageBlock>
      <br />
      <apex:commandButton value="Show These Fields" action="{!show}"/>
  </apex:form>
</apex:page>

 
VineetKumarVineetKumar
Seems like the accountList that you are passing to the second page, doesn't contain the Name field in the query that returned the rows for it.
Please check the query that is populating the accountList, and verify is all the fields that you need on your page is available in it.
Aryan05Aryan05
Hello Vineet,

Could you please point out the mistake, actually i'm not getting where i did wrong.
 
VineetKumarVineetKumar
Can you show me the code where you are referring setting the accountList value?
hitesh90hitesh90
Hello Aryan,

Try to use following updated controller code.

Apex Class:
public class DynamicCustomizableListHandler2 {
    // Resources we need to hold on to across requests
    private PageReference savePage;

    // This is the state for the list "app"
    private Set<String> unSelectedNames = new Set<String>();
    private Set<String> selectedNames = new Set<String>();
    private Set<String> inaccessibleNames = new Set<String>();

    public DynamicCustomizableListHandler2(ApexPages.StandardSetController controller) {
        loadFieldsWithVisibility(controller);
    }
    // Initial load of the fields lists
    private void loadFieldsWithVisibility(ApexPages.StandardSetController controller) {
        List<String> addDisplayFields = new List<String>();
        Map<String, Schema.SobjectField> fields = 
        Schema.SobjectType.Account.fields.getMap();
        for (String s : fields.keySet()) {
            if (s != 'Name') {  // name is always displayed 
                unSelectedNames.add(s);
            }
            if (!fields.get(s).getDescribe().isAccessible()) {
                inaccessibleNames.add(s);
            }
            addDisplayFields.add(s);            
        }
        controller.addFields(addDisplayFields);
    }

    // The fields to show in the list
    // This is what we generate the dynamic references from
    public List<String> getDisplayFields() { 
        List<String> displayFields = new List<String>(selectedNames);
        displayFields.sort();
        return displayFields;
    }
    
    // Nav: go to customize screen
    public PageReference customize() {
        savePage = ApexPages.currentPage();
        return Page.CustomizeDynamicList;
    }

    // Nav: return to list view
    public PageReference show() {
        // This forces a re-query with the new fields list
        return savePage; 
    }

    // Create the select options for the two select lists on the page
    public List<SelectOption> getSelectedOptions() { 
        return selectOptionsFromSet(selectedNames);
    }
    public List<SelectOption> getUnSelectedOptions() { 
        return selectOptionsFromSet(unSelectedNames);
    }
    
    private List<SelectOption> selectOptionsFromSet(Set<String> opts) {
        List<String> optionsList = new List<String>(opts);
        optionsList.sort();
        List<SelectOption> options = new List<SelectOption>();
        for (String s : optionsList) {
            options.add(new 
                SelectOption(s, decorateName(s), inaccessibleNames.contains(s)));
        }
        return options;
    }

    private String decorateName(String s) {
        return inaccessibleNames.contains(s) ? '*' + s : s;
    }

    // These properties receive the customization form postback data
    // Each time the [<<] or [>>] button is clicked, these get the contents
    // of the respective selection lists from the form
    public transient List<String> selected   { get; set; }
    public transient List<String> unselected { get; set; }

    // Handle the actual button clicks. Page gets updated via a
    // rerender on the form
    public void doAdd() {
        moveFields(selected, selectedNames, unSelectedNames);
    }
    public void doRemove() {
        moveFields(unselected, unSelectedNames, selectedNames);
    }
    
    private void moveFields(List<String> items, 
            Set<String> moveTo, Set<String> removeFrom) {
        for (String s: items) {
            if( ! inaccessibleNames.contains(s)) {
                moveTo.add(s);
                removeFrom.remove(s);
            }
        }
    }
}
Let me know if you have any question on this. Please mark this "Solved" if it helps.

Thank You,
Hitesh Patel
Email :- hiteshpatel.aspl@gmail.com
http://mrjavascript.blogspot.in/
 
DIPTULYA SHRIVASTAVADIPTULYA SHRIVASTAVA
Hitesh Patel,
Thanks ! I had similar issue and I tried your code. Your code works fine. Thanks a lot.

Deekay Shrivastava