Friday 27 June 2014

Pagination with maintaing the state of selected records to controller


Hi All,

I just got this piece of very useful code on the internet, thought it would be useful to share it to my viewers too, thanks to the guy who made this.

I have seen many people implemented pagination using salesforce, but recently I have come across a situation where I have to select list of records using pagination and process the records which are selected.

If use the StandardSetController, the check-boxes don’t maintain state if you check one and then go to the next page.

To solve this problem I have implemented custom Iterator.




First Class Code:
global 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;
   }  

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

   global 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;
   }
  
   global 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;
   }  
}

Second Class:
global Class AccountInner
{
    public boolean isSelected {get;set;}
    public Account acc {get;set;}
   
    public AccountInner(boolean isSelected, Account acc)
    {
        this.isSelected = isSelected;
        this.acc = acc;
    }
}

Visual force page :
<apex:page controller="Example1">
  <apex:form >
      <apex:sectionHeader title="Pagination" subtitle="Hi"/>
      <apex:pageBlock >
          <apex:pageBlockSection >
              <apex:pageBlockTable value="{!accInnerObj}" var="inner">
                  <apex:column >
                      <apex:inputCheckbox value="{!inner.isSelected}"/>
                  </apex:column>
                  <apex:column headerValue="Account">
                      <apex:outputText value="{!inner.acc.Name}" />
                  </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> 

Corresponding Controller:
public class Example1 {
   
    CustomIterable obj;
    public list<AccountInner> accInnerObj {get;set;}
   
    public Example1 () {      
        string sQuery = 'SELECT Id, Name, NumberOfEmployees FROM Account Limit 36';
        obj = new CustomIterable(sQuery);
        obj.setPageSize = 10;
        next();
    }
   
    public Boolean hasNext {
        get {
            return obj.hasNext();
        }
        set;
    }
   
    public Boolean hasPrevious {
        get {
            return obj.hasPrevious();
        }
        set;
    }
   
    public void next() {
        accInnerObj = obj.next();
    }
   
    public void previous() {
        accInnerObj = obj.previous();
    }

Monday 6 January 2014

Interactive JavaScript Charting for Salesforce Objects using - HighCharts


THE CHALLENGE
Salesforce provides a number of dashboards and reports, which support a variety of business charts. These charts can be Simpler to create and customize because they do not require programming in Visualforce or Apex. But it doesn't provide much information or interaction, need manual refresh to synchronize datas, limitations in axis selections.

SOLUTION:
Using Javascript with some custom componenets and visualforce pages we can create an intuitive charts for our organization.It offers variations on bar, line, area and pie charts commonly used in business graphics. If you need different chart types, or want to add advanced user or page interactions, you might want to investigate using a JavaScript charting library instead.This is more work, but allows greater customization.

What is JavaScript Charting?
JavaScript charting gives you an easy way to create customized business charts, based on data sets you create directly from SOQL queries, or by building the data set in your own Apex code. By combining and configuring individual data series, you can compose charts that display your data in ways meaningful to your organization.
JavaScript charts are rendered client-side using JavaScript. This allows charts to be animated and visually exciting, and chart data can load and reload asynchronously, which can make the page feel more responsive.

Why Would You Use JavaScript Charting?
Use JavaScript charting when the standard Salesforce charts and dashboards are insufficient, or when you wish to compose custom pages that combine charts and data tables in ways that are more useful to your organization.

Who Provides these?
There are many javascript code providers for the charting with complete documentation and libraries, some of the providers like HighCharts, extJs, GoogleCharts etc, provides various charts for different purposes.


                         Sample Implementation Using HighChart:
vISUALFORCE CODE:
1.  <apex:page controller="HighStockControllerdemo">
2.   
3.  <apex:includeScript value="{!URLFOR($Resource.Highstock, '/js/jquery.min.js')}"/>
4.  <apex:includeScript value="{!URLFOR($Resource.Highstock, 'js/highstock.js')}"/>
5.  <apex:includeScript value="{!URLFOR($Resource.Highstock, 'js/modules/exporting.js')}"/>
6.  <script language="JavaScript1.2" src="/js/functions.js"></script>
7.  <script src="/soap/ajax/9.0/connection.js" type="text/javascript"></script>
8.   
9.  <script type="text/javascript" language="javascript">
10.  $(function () {
11.     $('#container').highcharts({
12.         chart: {
13.             plotBackgroundColor: null,
14.             plotBorderWidth: null,
15.             plotShadow: false
16.         },
17.         title: {
18.             text: 'Invoice Statuses Report'
19.         },
20.         tooltip: {
21.             pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
22.         },
23.         plotOptions: {
24.             pie: {
25.                 allowPointSelect: true,
26.                 cursor: 'pointer',
27.                 dataLabels: {
28.                     enabled: true,
29.                     color: '#000000',
30.                     connectorColor: '#000000',
31.                     format: '<b>{point.name}</b>: {point.percentage:.1f} %'
32.                 },showInLegend: true
33.             }
34.         },
35.         series: [{
36.             type: 'pie',
37.             name: 'Invoice Chart',
38.             data: [{!LeaveStringColumn}]
39.                 }]
40.     });
41. });
42.  
43. </script>
44.  
45. <div id="wrapper">
46. <div id="container"></div>
47. </div>
48. </apex:page>



APEX CLASS:
1.  public  class HighStockControllerDemo{
2.   
3.  public List<Invoice__c> invList;
4.  public HighStockControllerdemo() {
5.  invList=[SELECT id,Status__c,Invoice_Total__c from Invoice__c];
6.  }
7.     
8.  public String getLeaveStringColumn()
9.  {
10. Map<String,Decimal> invMap = new Map<String, Decimal> {};
11.    for(Invoice__c invLoop:invList)
12.   {
13.       invMap.put(invLoop.Status__c, invLoop.Invoice_Total__c);
14.   }
15. return  coloumnclass.getColumn(invMap);
16.  
17. }
18. }







APEX CLASS:
1.  global class coloumnclass
2.  {
3.  global static String getColumn(Map<String,Decimal> mapIn) {
4.   
5.      String mapString = '';
6.      for (String fieldName : mapIn.keySet())
7.      {
8.      if (mapString != '')
9.      mapString += ',';
10.     mapString += '['+'\''+fieldName+'\''+','+mapIn.get(fieldName)+']';
11.     }
12.     return mapString;
13.        
14. }
15. }


SCREENSHOT





.....