Sunday, January 25, 2015

Onclick Javascript-AJAX Toolkit

When working with small amounts of data, use the AJAX Toolkit.
AJAX works best with relatively small amounts of data (up to 200 records, approximately six fields with 50 characters of data each). The larger the data set returned, the more time it will take to construct and deconstruct a SOAP message, and as the size of an individual record gets larger, the impact on performance becomes greater. Also, as more HTML nodes are created from the data, the potential for poor performance increases. Because browsers are not efficient, careful consideration needs to be given to browser memory management if you intend to display a large amount of data.

The following are examples of appropriate uses:
  • Updating a single record.
  • Modifying few fields of related child records.
  • Perform one or more simple calculations and then update a record.
Here I will be sharing basic sample code for 3 scenarios mentioned above.
  1. Updating a record
Support users can assign cases (assign to queue) to themselves by clicking on "Accept" button present in Case detail page. On click on "Accept" button, system will change the case ownerid to current logged in user. Below is sample code:


  1. Updating child records or list of records

Notify Contacts of Account to update their Contact details. Create a checkbox field(contact_update_required__c) in Contact. Create a workflow rule which will send email to all contacts to update their contact details whenever checkbox field is true. Create a related list button for Contact object “Update Contact Details” and add it to Contact related list on Account page layout. Whenever this button is clicked, onclick javascript modify the checkbox field to true in all related contacts of Account.



  1. Performing logic by calling apex method
There are few scenarios where you want to perform complex logic in apex class and want to execute that logic on click of button. For example, you want send notifications to attendees of event based on some logic. For this, you need to create global class and create webservice method and then call it from onclick javascript.


Others capabilities of AJAX  toolkit are:

  • Performing synchronous and asynchronous calls.
  • Query,create,edit,delete,undelete,merge and search records. 
  • Convert lead,send email and initiate approval process.
  • Use describe to get object and fields information.
Refer below URL for more reference on AJAX toolkit:

Friday, January 2, 2015

Creating custom lookup field in VF page for objects

Recently I got requirement in which I have to store information like Email template name, frequency of sending emails and few other fields in custom object. While selecting email template, salesforce standard look up pop should open which usually comes while creating Email Alerts (for selecting email template). Already custom fields like EmailTemplateid (text), and EmailTemplateName(text) were created in custom object. Also user want flexibility to create many records at once.

Below is sample code to create custom look up in VF page for email template:

Explanation:

First look at input elements:
  • Input text with id='Template_lkid' stores email template id.
  • Input text with id="Template_lkold" stores email template name.

Now look at javascript function:

JavaScript:openLookup('/_ui/common/data/LookupPage?lkfm=editPage&lknm='+templatenameid+'&lkrf=&epf=1&lktp=00X',670,'1','&lksrch=' + escapeUTF(getElementByIdCS(templatenameid).value.substring(0, 80)))";

About parameters which need to be set for replicating standard look up behaviour:

  • lknm : This specify the id of input text where selected value in pop up will display
  • lktp : This is object prefix( first 3 characters). in my case '00X' prefix for Email Template
  • lksrch : This is search parameter. If you specify text, then in pop up system will search and show results.
  • In order to store id of record selected in pop up, this function search input text field with id equal to value passed for lknm parameter appended by '_lkid'. For example, if we pass 'Template' as value for lknm parameters, then selected record id will be populated in input text field with id='Template_lkid'.

I have used <apex:inputtext/> tag inside pageblocktable, salesforce generate unique ids while rendering page. As it is repeating element, salesforce append numbers(index) starting from 0 (for first element) in front of id specified in apex:input tag. So in order to populate selected values to correct input text elements, I have created a counter variable in my wrapper. So whenever user clicks on lookup icon, I am passing the element id in javascript and extracting index (counter value) from it and then creating requird id which will be passed for lknm parameter.

In order to implement custom look up for other object, just change object prefix in javascriot openLookup function and it will work. For example, Account object prefix is '001'. Just change '00X' to '001' in order to open pop up for account records.

Snapshot











Hope this will help someone.
looking forward your comments and suggestions...

Monday, November 3, 2014

Headervalue not displayed in apex column tag

We have observed a strange behavior in headervalue property in <apex:column>tag. Header value won't display value if it is present within <apex:repeat> tags.

We were having a requirement where we need to display opportunity and its related competitor's record in one row. First Column will display opportunity fields and other columns will display field from different competitors related to opportunity. Number of columns will vary based on number of competitors. In order to display dynamic columns, we used <apex:column>  tags within <apex:repeat> tag. There are few fields which are common to opportunity and competitor object. User should be able to edit these fields for opportunity as well as for competitor in same page.

Below is sample code

Output:








In order to resolve this, we used Visualforce Dynamic Components. We created pageblocktable in apex and refereed it VF page.

Below is Code sample
Output after using Visualforce Dynamic Components:









Hope this might help you.

For more info on Visualforce Dynamic Components, Check below links:

https://www.salesforce.com/us/developer/docs/pages/Content/pages_dynamic_vf_components_intro.htm
https://developer.salesforce.com/page/Dynamic_Visualforce_Components

Looking forward for everyone's comment and suggestions.


Monday, September 29, 2014

Quote to Cash Certification Overview

Quote-to-Cash Certification, is a free certification program designed for quoting and contracting knowledge. This certification consists of five video modules, followed by an online test to earn certification badge.

You need to register for this course on http://www.apttus.com/certification/ . After registration, you will get access to 5 training videos and study guide which will help you to clear the certification quiz.

In short, Quote to cash is integrated package of below mentioned functionality:
  • Integrated CPQ, contract management & revenue management-
  • Compensation management that incents reps to offer better deals-
  • Echo sign e-Signature for speedy quoting and contract cycles
  • Sync order details to enterprise resource planning (ERP) and Salesforc

Different modules involved:
  • Quote-to-Cash- Introduction and its benefits
  • Introduction to Configure, Price, Quote (CPQ)
  • Minimizing Risk & Maximizing Revenue with Contract Management
  • Getting Real Insight Into Cash with Effective Revenue Management
  • Quote-to-Cash Success on Salesforce1

This training module will give you functional knowledge of Quote to cash process, helps in understanding CPQ and will explain what are challenges customers are facing to close deals faster . It also describe the functionality provide by APTTUS –Quote to cash package in order to deal with all the challenges while proposing deals or closing the deals.

Features which I like the most in Quote to cash:
  • 100% native to Salesforce so need to integrate it with any 3rd party quoting tool.
  • Guide selling: It provide an ability to configure this app in such a way that sales reps can ask question from customer related to their requirement s and interest and system will populate the suggested products
  • Marked as favorites:  Sales reps can specify products or combination of different products as favorites so that they don’t have to search it every time.
  • Ability to configure discounts at account or partner level, quote level and quote line item level.
  • Availability of API’s related to all CPQ functionality so that developers can customize the app based on customer requirements.
  • Ability to configure E-commerce for external customer easily by using Exposed API’s provided by APTTUS.

Friday, September 12, 2014

Using the Force.com CLI

Force.com CLI tool allows you to interact directly with Force.com from your command-line.
Functionality includes exporting metadata and packages created in SFDC to a local directory, browsing data objects, executing SOQL queries, executing APEX code,managing custom objects etc.


Download Force.CLI from https://force-cli.heroku.com/

Download Force.com CLI executable file and store it in some folder. Suppose my folder name is "CLI Demo" present in E: drive.


Now Open Command prompt  and go to CLI Demo Folder and use below commands:
E:\CLI Demo>force version


If you are getting version information then it means CLI is configured correctly. Otherwise if you getting some error, then set system variable by navigating computer->my properties-Advanced system settings->Environment variables. Provide CLI Demo folder location in path variable.


Once Force.com CLI is configured properly, then we can use it to export package created in SFDC to local directory. Follow below steps:
  1. Create a package: Go to SetUp-> Create->Packages. Create a new package and include all elements which you want to export from SFDC.
  2.          Now you can go to command prompt and enter following commands:
             First we need to login to SFDC instance in order to fetch package

        For Production and developer sandbox use
        force login -i=login.salesforce.com  -u=USERNAME  -p=PASSWORD+SECURITYTOKEN
                           or
        force login -u=USERNAME  -p=PASSWORD+SECURITYTOKEN

       For Sandbox
        force login -i=test.salesforce.com -u=USERNAME  -p=PASSWORD+SECURITYTOKEN

            To fetch package details:

      force fetch package PACKAGENAME --unpack

      In our case package name is “ForceCLIDemoPackage” so enter

      fetch package ForceCLIDemoPackage --unpack


Now metadata folder is created in CLI Demo folder which contain all components information present in package. If you open it, you will see package.xml containing all components list.


Note: If you deploy components in SFDC org using Workbench, then Force.com CLI will help you create package.xml file easily. You don’t have to manually create package.xml file. Just create package in your source org and Fetch it with Force.com CLI and the zip all contents (package.xml and all folders present in ForceCLIDemoPackage). After this deploy the zip file using workbench to target org.

Available commands:
   login     Log in to force.com
   logout    Log out from force.com
   logins    List force.com logins used
   active    Show or set the active force.com account
   whoami    Show information about the active account
   sobject   Manage standard & custom objects
   field     Manage sobject fields
   record    Create, modify, or view records
   bulk      Load csv file use Bulk API
   fetch     Export specified artifact(s) to a local directory
   export    Export metadata to a local directory
   fetch     Export specified artifact(s) to a local directory
   import    Import metadata from a local directory
   query     Execute a SOQL statement
   apex      Execute anonymous Apex code
   oauth     Manage ConnectedApp credentials
   version   Display current version
   update    Update to the latest version
   push      Deploy single artifact from a local directory
   password  See password status or reset password
   help      Show this help

Run 'force help [command]' for details.





Tuesday, June 10, 2014

Displaying all submitted records for an approval process along with their status in VF Page

Few days back, I got requirement from one of my friends to list all approval process in Visualforce Page in picklist and when user select any approval process, the system should display all the records which are submitted for approval along with their status.
In order to achieve this, I have created a VF page and used REST API to get list of all approval process present in org. After getting the list of approval process in JSON, I parsed the response and displayed the approval process names in picklist. When user select particular approval process, system will query all processinstances records and then with the help of TargetObjectid, it will fetched the Ojbect name. Then system will match the object name related to approval process with object related to targetobjectid.
If it got matched, then processInstance record will be stored in list and will be displayed to user.

VF Page Snapshot:









Notes:

  • First create remote site setting with Remote Site URL as https://xxx.salesforce.com where xxx domain name like ap1,na1 etc.
  • I tried to filter the number of processInstance records by putting where clause but it didn't work for me. So I queried all processInstance records.
  • We can specify where clause on createddate or lastmodifieddate by giving an option to user to select date range. We can display two more fields as startdate and enddate on VF page and system will display only processinstance records created or modified between these 2 dates.

Looking forward to your comments and suggestions.

Below is VF Page Code:

<apex:page controller="DisplayApprovedRecordsController" action="{!FetchAllApprovalProcess}">
<apex:form >
    <apex:pageblock title="Approval processess List">      
        <apex:pageblocksection columns="3">
            <apex:pageblockSectionItem >
                <apex:outputLabel value="Select" for="apr"></apex:outputLabel>
                <apex:selectList value="{!selectedApprovalProcess}" size="1" id="apr">
                    <apex:selectOptions value="{!ApprovalWrapperList}"></apex:selectOptions>
                    <apex:actionsupport event="onchange" action="{!FindRecords}"/>
                </apex:selectList>
            </apex:pageblockSectionItem>          
        </apex:pageblocksection>      
        <apex:pageblockSection title="Approved Records" columns="1" >
            <apex:pageblockTable value="{!recordList}" var="rec" rendered="{!recordList.size>0}">
                <apex:column headerValue="Name">
                    <apex:outputlink value="/{!rec.TargetObjectId}">{!rec.TargetObject.name}</apex:outputlink>
                </apex:column>              
                <apex:column headerValue="Status">
                    <apex:outputText value="{!rec.status}"></apex:outputText>
                </apex:column>
            </apex:pageblockTable>          
            <apex:outputpanel rendered="{!recordList.size==0}">
                <apex:outputText value="No records to display"></apex:outputText>
            </apex:outputpanel>      
        </apex:pageblockSection>
    </apex:pageblock>
</apex:form>
</apex:page>

Apex Class Code:

public class DisplayApprovedRecordsController {
    public List<ApprovalWrapper> ApprovalProcessList{get;set;}//list to store all approval process
    public String selectedApprovalProcess{get;set;}
    Public list<ProcessInstance> recordList{get;set;} //list to store processInstance records to display on UI

    public List<selectoption> getApprovalWrapperList(){
        List<selectoption> temp=new List<selectoption>();
        temp.add(new selectoption('','--Select--'));
        for(String ap:approvalMap.keyset()){
            temp.add(new selectoption(ap,ap));
        }
        return temp;
    }
    public DisplayApprovedRecordsController (){
        ApprovalProcessList=new List<ApprovalWrapper>();
        recordList=new list<ProcessInstance> ();
    }
    public map<String,ApprovalWrapper> approvalMap=new map<String,ApprovalWrapper>();
    public void FetchAllApprovalProcess(){      
        HttpRequest req = new HttpRequest();
        req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
        req.setHeader('Content-Type', 'application/json');
        String domainUrl=URL.getSalesforceBaseUrl().toExternalForm();
        system.debug('********domainUrl:'+domainUrl);
        String endpointUrl=domainUrl+'/services/data/v30.0/process/approvals/';
        req.setEndpoint(endpointUrl);
        req.setMethod('GET');      
        Http h = new Http();
        HttpResponse res = h.send(req);
        system.debug(res.getBody());
        String ss=res.getBody();
        string newjsondata = ss.replace('"object"','"objectName"');
       
        // Parse entire JSON response.
        JSONParser parser = JSON.createParser(newjsondata );
        while (parser.nextToken() != null) {
            // Start at the array of invoices.
            if (parser.getCurrentToken() == JSONToken.START_ARRAY) {
                while (parser.nextToken() != null) {
                    // Advance to the start object marker to
                    //  find next approval process object.
                    if (parser.getCurrentToken() == JSONToken.START_OBJECT) {
                        // Read entire  approval process object
                        ApprovalWrapper apr= (ApprovalWrapper)parser.readValueAs(ApprovalWrapper.class);
                        system.debug('Approval name: ' + apr.name);
                        system.debug('Id: ' + apr.id);
                        ApprovalProcessList.add(apr);
                        // Skip the child start array and start object markers.
                        parser.skipChildren();
                    }
                }
            }
        }
        system.debug('********ApprovalProcessList:'+ApprovalProcessList);
        for(ApprovalWrapper aw:ApprovalProcessList){
            approvalMap.put(aw.name,aw);
        }
}
public Pagereference FindRecords(){
recordList=new list<ProcessInstance> ();
        if(selectedApprovalProcess!=null && selectedApprovalProcess!=''){
            recordList=new list<ProcessInstance> ();
            String queryString='Select Id, TargetObjectId,TargetObject.name, Status From ProcessInstance Limit 10000';
            System.debug('*********queryString:'+queryString);
            List<ProcessInstance> temp=Database.query(queryString);
            ApprovalWrapper aw=new ApprovalWrapper();
            aw=approvalMap.get(selectedApprovalProcess);
            String ObjName=aw.objectName;
            recordList=new List<Processinstance>();
            For(ProcessInstance sb:temp){
                String ObjectName=String.valueof(sb.TargetObjectId.getSObjectType());
                system.debug('****ObjectName:'+ObjectName);
                if(Objectname.equalsignorecase(ObjName)){
                    recordList.add(sb);
                }
            }
            System.debug('*********recordList:'+recordList);
       }
        return null;
    }    
    public class ApprovalWrapper{
        public String description{get;set;}
        public String id{get;set;}
        public String name{get;set;}
        public String objectName{get;set;}
        public Integer sortOrder{get;set;}
    }
}

Monday, November 26, 2012

Viewing and Editing all Custom Settings in Visualforce Page


To see or edit custom setting records, we navigate to each custom setting, click on manage button and edit/ view custom settings records.

In order to avoid this navigation for all custom setting, I thought of creating a VF page where we can select custom setting present in organization and view/ edit records related to the selected custom settings on the same VF Page.

In order to achieve this, I have created a VF page named as "Sunil_CSDetails". Also I have created a batch class which will check for custom settings present in organization and will store their API names in one custom object (say "CS_Name__c"). You can use standard name field or custom text field (say "Name__c") to store API name of custom object.


User will click on Refresh button in order to fetch all custom settings present in the organization. After clicking on Refresh button, user will see progress bar with status. When the operation is finished, a new button will appear on the page with a message to click on that button.


After clicking on "Display Options" button, the page will display a picklist with all available custom settings and records related to selected option.
Now you can select any custom settings present in organization and view related records. Click on "Edit" button in order to edit any custom settings records.

You can download zip file from the link below which contains apex classes, VF page and custom objects.

Download Apex class and VF Page code from here

Looking forward to your comments and views.





Refer Below Links for Salesforce Interview Questions