3

UPDATE: CONTROLLER

public class CustomIterable implements Iterator<list<AccountInner>>{ 

   List<Account> accs {get; set;} 
   list<AccountInner> accInnerList {get; set;} 
   list<AccountInner> accInnerListRequested {get; set;} 
   AccountInner accInnerObj;
   Integer i {get; set;} 
   public Integer setPageSize {get; set;} 

   public CustomIterable(string sQuery){ 
       //accs = [SELECT Id, Name, NumberOfEmployees FROM Account Limit 36]; 
       accs = Database.Query(sQuery);
       accInnerList = new list<AccountInner>(); 
       accInnerListRequested = new list<AccountInner>();     
       for(Account a : accs) {
            accInnerObj = new AccountInner(false, a);
            accInnerList.add(accInnerObj);
       } 
       setPageSize = 10;
       i = 0; 
   }   

   public boolean hasNext(){ 
       if(i >= accInnerList.size()) {
           return false; 
       } else {
           return true; 
       }
   } 

   public boolean hasPrevious(){ 
       system.debug('I am in hasPrevious' + i);
       if(i <= setPageSize) {
           return false; 
       } else {
           return true; 
       }
   }   

   public list<AccountInner> next(){       
       system.debug('i value is ' + i);
       accInnerListRequested = new list<AccountInner>(); 
       integer startNumber;
       integer size = accInnerList.size();
       if(hasNext())
       {  
           if(size <= (i + setPageSize))
           {
               startNumber = i;
               i = size;
           }
           else
           {
               i = (i + setPageSize);
               startNumber = (i - setPageSize);
           }

           system.debug('i value is =====' + i);
           system.debug('i value is 2==== ' + (i - setPageSize));

           for(integer start = startNumber; start < i; start++)
           {
               accInnerListRequested.add(accInnerList[start]);
           }
       } 
       return accInnerListRequested;
   } 

   public list<AccountInner> previous(){      
       accInnerListRequested = new list<AccountInner>(); 
       system.debug('i value is previous before =====' + i);
       integer size = accInnerList.size(); 
       if(i == size)
       {
           if(math.mod(size, setPageSize) > 0)
           {    
               i = size - math.mod(size, setPageSize);
           }
           else
           {
               i = (size - setPageSize);
           } 
       }
       else
       {
           i = (i - setPageSize);
       }

       system.debug('i value is previous =====' + i);
       system.debug('i value is 2previous ==== ' + (i - setPageSize));

       for(integer start = (i - setPageSize); start < i; ++start)
       {
           accInnerListRequested.add(accInnerList[start]);
       } 
       return accInnerListRequested;
   }   
}


public Class AccountInner
{
    public boolean isSelected {get;set;}
    public Account acc {get;set;}

    public AccountInner(boolean isSelected, Account acc)
    {
        this.isSelected = isSelected;
        this.acc = acc;
    }
}

UPDATE:

When the user click on checkbox I want to display the detail information of that particular record in a grid

When the user Select ALL checkbox then iterate all the selected checkbox and display the related detail information in a grid.

I have two phase on my VFP and fist half of the page is to display all the Accounts data with checkbox which I have done as shown below but I need help in the second half and my question is: When the user check on the checkbox I wan to populate a second grid with related data how would I do that?

enter image description here

Here is my VFP code:

<script type="text/javascript">
    function selectAllCheckboxes(obj,receivedInputID){
        var inputCheckBox = document.getElementsByTagName("input");                  
        for(var i=0; i<inputCheckBox.length; i++){          
            if(inputCheckBox[i].id.indexOf(receivedInputID)!=-1){                                     
                inputCheckBox[i].checked = obj.checked;
            }
        }
    }
</script>    
 <apex:form >
      <apex:sectionHeader title="Pagination" subtitle="Hi"/>
      <apex:pageBlock >
          <apex:pageBlockSection >
              <apex:pageBlockTable value="{!accInnerObj}" var="inner">
                  <apex:column headerValue="Select All">
                      <apex:facet name="header">
                        <apex:inputCheckbox onclick="selectAllCheckboxes(this,'inputId')"/>
                    </apex:facet>

                      <apex:inputCheckbox value="{!inner.isSelected}" id="inputId"/>
                  </apex:column> 
                  <apex:column headerValue="Account"> 
                      <apex:outputText value="{!inner.acc.Name}" />
                  </apex:column>    
                  <apex:column headerValue="NumberOfEmployees "> 
                      <apex:outputText value="{!inner.acc.NumberOfEmployees }" />
                  </apex:column>

              </apex:pageBlockTable>
          </apex:pageBlockSection>
      </apex:pageBlock>

      <br/>
      <apex:commandButton value="<<Previous" action="{!previous}" rendered="{!hasPrevious}"/>
      <apex:commandButton value="Next >>" action="{!next}" rendered="{!hasNext}"/>

  </apex:form>
</apex:page>
  • 1
    What exactly are you trying to populate in your second grid? What happens when multiple checkboxes (or all) are checked at the same time? Please narrow down your problem, the question above is too broad and it's likely to be closed by the community unless you update it with more details. – Boris Bachovski Jul 2 '15 at 0:01
  • @Bachovski: I have updated my question please see if you still not clear. – Nick Kahn Jul 2 '15 at 0:04
  • 1
    What information would you like to display in the 2nd table? – Boris Bachovski Jul 2 '15 at 0:20
  • just to make it very simple I like to have SELECT Id, Name FROM Account – Nick Kahn Jul 2 '15 at 0:22
  • 1
    You already have the account info in the first table. What is the "related data" that you're referring to that you want to display in the second table? – Boris Bachovski Jul 2 '15 at 0:27
1

Let's assume your custom object is called Invoice__c and you have the following fields on that object:

  • Account__c - lookup to Account
  • Amount__c - invoice amount
  • Name - standard field (text or auto number)

In this example we'll list all invoices related to a selected account in a separate table.

Due to the complexity, I don't think pageBlockTable will cater for it, so you'll need to use a standard HTML table and iterate through the records using apex:repeat. Also you'll see some css classes and javascript events on the custom table - these are borrowed from the standard Salesforce.com interface in order to reproduce the UX for the custom table.

First thing you need to do is change your wrapper class to incorporate the list of related invoice records to the account and query to populate that list:

public with sharing class DependentTableController
{
    public List <AccountWrapper> accInnerObj {get; set;}

    public class AccountWrapper
    {
        public Boolean isSelected {get; set;}
        public Account acc {get; set;}
        public List <Invoice__c> invoices {get; set;} // new
    }

    public void init()
    {
        // Assume you have something like this
        accInnerObj = new List <AccountWrapper> ();

        // Map the account ID to the wrapper object
        Map <Id, AccountWrapper> accountsMap = new Map <Id, AccountWrapper> ();

        for (Account account : [SELECT Id, Name FROM Account])
        {
            AccountWrapper accWrapper = new AccountWrapper();
            accWrapper.acc = account;
            accWrapper.isSelected = false;
            accWrapper.invoices = new List <Invoice__c> ();
            accInnerObj.add(accWrapper);
            accountsMap.put(account.Id, accWrapper);
        }

        // Query the other object's records where the lookup id to the account is in our map
        for (Invoice__c invoiceRecord : [SELECT Id, Name, Amount__c, Account__c, Account__r.Name FROM Invoice__c WHERE Account__c IN :accountsMap.keySet()])
        {
            accountsMap.get(invoiceRecord.Account__c).invoices.add(invoiceRecord);
        }
    }
}

Then in your visualforce page you need to create an action function that you'll call every time there is a change in the selection of the accounts, which will re-render the second table.

The second table has 2 apex:repeat elements. The first one goes through each of the wrapper objects and checks whether there are any selected. If there is a selected account and has 1 or more related invoices, a second apex:repeat element will iterate through the related invoices and output the relevant information:

<apex:page showHeader="true" sidebar="true" controller="DependentTableController" action="{!init}">

    <script type="text/javascript">
        function selectAllCheckboxes(obj,receivedInputID){
            var inputCheckBox = document.getElementsByTagName("input");
            for(var i=0; i<inputCheckBox.length; i++){
                if(inputCheckBox[i].id.indexOf(receivedInputID)!=-1){
                    inputCheckBox[i].checked = obj.checked;
                }
            }
        }
    </script>

    <apex:form >
        <apex:sectionHeader title="Pagination" subtitle="Hi"/>
        <apex:actionFunction name="selectedAccountChanged" reRender="secondTable" />
        <apex:pageBlock >
            <apex:pageBlockSection >
                <apex:pageBlockTable value="{!accInnerObj}" var="inner">
                    <apex:column headerValue="Select All">
                        <apex:facet name="header">
                            <apex:inputCheckbox onclick="selectAllCheckboxes(this,'inputId'); selectedAccountChanged();"/>
                        </apex:facet>
                        <apex:inputCheckbox value="{!inner.isSelected}" id="inputId" onclick="selectedAccountChanged();" />
                    </apex:column>
                    <apex:column headerValue="Account">
                        <apex:outputText value="{!inner.acc.Name}" />
                    </apex:column>
                    <!-- the rest of your code -->
                </apex:pageBlockTable>
            </apex:pageBlockSection >
        </apex:pageBlock>

        <apex:pageBlock id="secondTable" mode="detail">
            <table class="list" width="100%" cellpadding="0" cellspacing="0">
                <tr class="headerRow" >
                    <th style="width: 33%;">Account Name</th>
                    <th style="width: 33%;">Invoice Number</th>
                    <th>Amount</th>
                </tr>
                <apex:repeat value="{!accInnerObj}" var="accountWrapper">
                    <apex:outputPanel layout="none" rendered="{!accountWrapper.isSelected && accountWrapper.invoices.empty == false}">
                        <apex:repeat value="{!accountWrapper.invoices}" var="invoice">
                            <tr class="dataRow even first" onfocus="if (window.hiOn){hiOn(this);}" onblur="if (window.hiOff){hiOff(this);}" onmouseout="if (window.hiOff){hiOff(this);} " onmouseover="if (window.hiOn){hiOn(this);} ">
                                <td><apex:outputText value="{!invoice.Account__r.Name}"/></td>
                                <td><apex:outputText value="{!invoice.Name}"/></td>
                                <td><apex:outputText value="{!invoice.Amount__c}"/></td>
                            </tr>
                        </apex:repeat>
                    </apex:outputPanel>
                </apex:repeat>
            </table>
        </apex:pageBlock>
    </apex:form>

</apex:page>
  • 1+ Thanks you for your effort and I will work on this and get back to you – Nick Kahn Jul 3 '15 at 2:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.