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
vijay kumar 495vijay kumar 495 

list view print functionality in lightning

I have developed code to over come limitation of print option for list view.
VF Page
<apex:page sidebar="false" standardStylesheets="false" cache="false" standardController="Account" recordSetVar="accounts" lightningStylesheets="true">
    <button id="upload-button" onclick="window.print();" style="margin-left: 50%;" Class="slds-button">Print</button>
    <apex:includeLightning />
    <div id="lightning" ></div> 
    <script>
        $Lightning.use("c:ListView", function() {
          $Lightning.createComponent("c:ListViewComponent",
          { label : "" },
          "lightning",
          function(cmp) {
             
          });
        });
    </script>
</apex:page>


Controller class
public with sharing class ListViewController {
    
    // Method to get all list view option available for the Account object 
    @AuraEnabled
    public static List<SelectOption> getListViews(){
        SelectOption  lstView=new SelectOption ('--None--','--None--');
        List<SelectOption> listviews = new List<SelectOption>();
        listviews.add(lstView);
        for(ListView lstObj : [SELECT Id, Name FROM ListView WHERE SobjectType = 'Account' order by name ASC]){
            listviews.add(new SelectOption (lstObj.id,lstObj.name));
        }
        return listviews; 
    }
    // Method to get the Account records based on the selected list view
    @AuraEnabled  
    public static DynamicTableMapping getFilteredAccounts(String filterId){
        list<string> headervalue =new list<string>();
        HttpRequest req = new HttpRequest();
        String baseUrl = URL.getSalesforceBaseUrl().toExternalForm();
        String endPoinURL = baseUrl+'/services/data/v32.0/sobjects/Account/listviews/'+filterId+'/describe';
        req.setEndpoint(endPoinURL);
        req.setMethod('GET');
        req.setHeader('Authorization',  'Bearer ' + UserInfo.getSessionId());
        Http http = new Http();
        HTTPResponse response = http.send(req);
        Map<String, Object> tokenResponse = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
        String query = (String) tokenResponse.get('query');
        system.debug('query--->'+query);
       for(string s:query.split(',')){
            s=s.trim();    
            if(s.startsWith('SELECT')){
                headervalue.add((s.removeStart('SELECT')).trim());        
            }else if(!s.startsWith('SYSTEMMODSTAMP') && !s.equalsIgnoreCase('SYSTEMMODSTAMP FROM ACCOUNT ORDER BY NAME ASC NULLS FIRST') && !s.contains('ASC')){
                headervalue.add(s.trim());
            }
        }
        
        List<ObjectValueMap> AccountList = new List<ObjectValueMap>();
        
        for(Account accountObj : database.query(query)){
            
            Map<String, Schema.SObjectField> objectFields = Account.getSObjectType().getDescribe().fields.getMap();
            list<FieldValues> fieldValue=new list<FieldValues>();
            for(string s:headervalue){
                Schema.DescribeFieldResult dr;
                if (objectFields.containsKey(s)) 
                      dr = objectFields.get(s).getDescribe();
                if(null!=dr)
                    fieldValue.add(new FieldValues(string.valueof(null==accountObj.get(dr.getName())?'':accountObj.get(dr.getName()))));            
                else
                    fieldValue.add(new FieldValues(string.valueof('')));
            }
            AccountList.add(new ObjectValueMap(accountObj,fieldValue));
        }
        
        return new DynamicTableMapping(headervalue,AccountList);        
    }
      
}



Lightning component
<aura:component controller="ListViewController" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:attribute name="AccountListViewList" type="SelectOption[]"/>
    <aura:attribute name="AccountList" type="DynamicTableMapping"/>
    <aura:attribute name="fieldList" type="string[]"/>
    <ui:inputSelect class="slds-select slds-size_small" aura:id="selectedViewId" label="Account View" change="{!c.getFilteredAccount}">
        <aura:iteration items="{!v.AccountListViewList}" var="listview">
            <ui:inputSelectOption text="{!listview.value}" label="{!listview.label}"/>
        </aura:iteration>
    </ui:inputSelect>
   
    <br/><br/>
    
    <table class="slds-table slds-table_bordered slds-table_cell-buffer">
        <thead>
            <tr class="slds-text-title_caps">
                <aura:iteration items="{!v.fieldList}" var="item">
                    <th scope="col">
                        <div class="slds-truncate" title="{!item}">{!item}</div>
                    </th>
                </aura:iteration>
            </tr>
        </thead>
        <tbody>
        <aura:iteration items="{!v.AccountList}" var="item" indexVar="index">
        <tr>
       
            <aura:iteration items="{!item.values}" var="item1">
                <td>
                     {!item1.value}   
                </td></aura:iteration>
        </tr>
        </aura:iteration>
        </tbody>
    </table>
</aura:component>


Component controller JS
({
    doInit : function(component, event, helper){
        var action = component.get("c.getListViews");
        action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.AccountListViewList",response.getReturnValue());
            }
        });
       
        $A.enqueueAction(action);
    },
    getFilteredAccount : function (component, event, helper) {
        var selected = component.find("selectedViewId").get("v.value");
        var action = component.get("c.getFilteredAccounts");
        action.setParams({filterId : selected});
        action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.AccountList",response.getReturnValue().value);
                component.set("v.fieldList",response.getReturnValue().headervalues);
            }
        });
        
        $A.enqueueAction(action); 
    },
    
})


Helper classes
public class DynamicTableMapping {
    
    @AuraEnabled
    public list<string> headervalues{get;set;}
    @AuraEnabled 
    public list<ObjectValueMap> value{get;set;}
    
    public DynamicTableMapping(list<string> headervalues,list<ObjectValueMap> value){
        this.headervalues=headervalues;
        this.value=value;
    }
}

--- Value map class--

public class ObjectValueMap {
	
    @AuraEnabled
    public account account{get;set;}
    @AuraEnabled
    public list<fieldValues> values{get;set;}
    
    public ObjectValueMap(account acc,list<fieldValues> values){
    	this.account=acc;
        this.values=values;
    }
}

-- Field values class--
public class FieldValues {
	@auraenabled
    public object value{get;set;}
    
    public FieldValues(object value){
        this.value=value;
    }
}

You can modify this code any other object you wish to implement.
Create listview button with the VF page.
Emerson BrophyEmerson Brophy
Hi Vijay, could you please provide a few screenshots of what the outputs of this method look like? Thanks
vijay kumar 495vijay kumar 495
HI Emerson, Please find the screen shots
Page viewPrint view
Emerson BrophyEmerson Brophy
Thanks Vijay
Sumanth Dev OrgSumanth Dev Org
Hi Vijay

Thanks , very useful post. 

I was just wondering , how can i avoid ,
1) Following fields from query in Controller class (line 28) Id', 'CurrencyIsoCode' ,'CreatedDate','LastModifiedDate ?
 
2) Avoid labels being API names and display field Labels instead of API name on tabel header ?

Thanks in advance
Sumanth
bhanu_prakashbhanu_prakash
Hi Vijay,
nice post to got through it. can we make it as dynamic ?
John Sellers 22John Sellers 22
Thanks so much Vijay, Do you have any updates for this since November? It looks very promising, but I am getting an unexpected error in my controller class and helper class related to DynamicTableMapping attribute not being supported. 
Ashish TakkeAshish Takke
Hi Vijay,
Could you please also share Test class for same? 

Regards,
Ashish Takke
Eric KokmanianEric Kokmanian
I am getting this message : "An internal server error has occurred. Error ID: 1649376311-855 (-697475282)". Anyone has an idea behind this?
I am seeing the button and when pressing it it opens up a printing form but with no table of Accounts...
lkatneylkatney
Hi Guys,

This post is really helpful. Please put all this code to this tool Playground (https://playg.app) so that it can be reused & tested efficiently for other users.

Thanks
Lakshay - Playground

Playground is a Salesforce online community to share solutions free of cost that can be used by anyone & with one click deploy technology, it gives hassle-free experience to test these solutions quickly. Check this out at https://playg.app to see existing/upload your solutions
vijay kumar 495vijay kumar 495
Sorry guys, i was away for some time.. let me answer your questions. Does any one require help implementing this?
vijay kumar 495vijay kumar 495
HI Lakshay,

Uploaded to Playgorund as well.
lkatneylkatney
Hi Vijay,

Thanks for this quick upload. This is really helpful. I am putting its link here as well for other people.

https://www.playg.app/play/print-list-view-in-lightning

Thanks
Lakshay

Playground is a Salesforce online community to share solutions free of cost that can be used by anyone & with one click deploy technology, it gives hassle-free experience to test these solutions quickly. Check this out at https://playg.app to see existing/upload your solutions
Simangaliso Mathenjwa 6Simangaliso Mathenjwa 6
Hi Vijay, I am getting an error "AuraEnabled methods do not support return type of List<System.SelectOption>" when I try to save ListViewController class, is there a solution for this
vijay kumar 495vijay kumar 495
@Simangaliso Mathenjwa 6

Please share error screen shot. i have just checked above code saved without error.

Thanks,
Vijay.
Simangaliso Mathenjwa 6Simangaliso Mathenjwa 6
Hi Vijay, please see the screenshot as requestedUser-added image
vijay kumar 495vijay kumar 495
HI Simangaliso,

Change list<selectoption> to list<wrapperClass> and return the wrapper class list.
you have to inner wrapper class in controller.
try below code
 
public with sharing class ListViewController{


	// Method to get all list view option available for the Account object 
    @AuraEnabled
    public static List<wrapperClass> getListViews(){
        wrapperClass  lstView=new wrapperClass('--None--','--None--');
        List<wrapperClass> listviews = new List<wrapperClass>();
        listviews.add(lstView);
        for(ListView lstObj : [SELECT Id, Name FROM ListView WHERE SobjectType = 'Account' order by name ASC]){
            listviews.add(new wrapperClass (lstObj.name,lstObj.id));
        }
        return listviews; 
    }
	
	public class wrapperClass{
		public string pickLstvalue;
		public string pickListId;
		public wrapperClass(string pickListValue,string listid){
			this.pickLstvalue=pickListValue;
			this.pickListId=listid;
		}
	}
}

 
Simangaliso Mathenjwa 6Simangaliso Mathenjwa 6
@Vijay, thank you so much, worked like a charm
venkat bojjavenkat bojja
Hi @vijay kumar 495

I'm getting below error while saving the Lightning Component.
"
Failed to save ListViewComponent.cmp: Invalid <aura:attribute> type: DynamicTableMapping: Source"
And tried to preview the VF page and getting "An internal server error has occurred" Error.
FYI:
User-added image
User-added image


Thanks,
Venkat.