Jun 27, 2011

Display Picture in Contact

What if I want to display my image on contact, and I frequently change it also. The answer in general is, create a visualforce page page and override it to native contact detail page.


This doesn't sounds good to me, am not happy overriding native pages provided by Salesforce. So I finally decided to put my head together and think how I can do this in another way.


Idea came in mind that what if I use Notes and Attachments on Contact object. Yes! I have uploaded some of my pictures in Notes and Attachment and provided a button on detail page to select one of them.




When you click on the "Set Profile Picture" a pop up gets open where all valid images are shown with radio option as shown in above screen. Selected image is displayed on contact like this,



How can you implement this?? Follow some simple steps.

Make sure you copy all Labels, Names etc correctly.


1) Create field of Type : "Text" with Field Label : "StoreImageUrl" and Field Name : "StoreImageUrl" (Lenght - 255) -> Make it visible to all profiles but do not show this on any page layout. This is for internal use only.


2) Create another field of Type : "Formula" with Field Label : "&nbsp" and Field Name : "Image" with return type "Text"


Formula will contain
IF( StoreImageUrl__c != null , IMAGE( StoreImageUrl__c , '' , 100 , 100 ) , IMAGE('' , '' , 0 , 0))
Make it visible for all profiles and show it at top on all layouts.


3) Create an Apex Class
public class DisplayImagesController
{
    //Parent Contact
    private String ContactId ;
    //Image selected from UI
    public String selectedImage {get; set;}
    
    public DisplayImagesController()
    {
        //Fetching contact Id
        ContactId = ApexPages.CurrentPage().getParameters().get('Id') ;
        selectedImage = '' ;
    }
    
    public boolean validateImage(String image)
    {
        String Regex = '([^\\s]+(\\.(?i)(jpg|png|gif|bmp))$)';
        Pattern MyPattern = Pattern.compile(Regex);
        Matcher MyMatcher = MyPattern.matcher(image);
        return MyMatcher.matches() ;
    }
    
    public List<SelectOption> getItems()
    {
        List<SelectOption> options = new List<SelectOption>(); 
        
        //All attachments related to contact
        List<Attachment> attachLst = [SELECT Id , Name FROM Attachment WHERE ParentId =: ContactId] ;
        
        //Creating option list
        for(Attachment att : attachLst)
        {
            String imageName = att.name.toLowerCase() ;
            if(validateImage(imageName))
            {
                options.add(new SelectOption(att.Id , att.Name));
            }
        }
        
        return options ;
    }
    
    public PageReference SaveImage()
    {
        //Contact to update
        List<Contact> conToUpdate = new List<Contact>() ;
        conToUpdate = [select id,StoreImageUrl__c from contact where id =: ContactId] ;

        //Inserting image parth
        if(conToUpdate.size() > 0)
        {
            conToUpdate[0].StoreImageUrl__c = 'https://c.ap1.content.force.com/servlet/servlet.FileDownload?file=' + selectedImage ;
            update conToUpdate[0] ;
        }
        return null ;
    }
}


4) Create a visualforce page with Label and Name "DisplayImages"
<apex:page id="pg" controller="DisplayImagesController" sidebar="false" showHeader="false">
<script>
    function validateRadio()
    {
        var elLength = document.getElementById('pg:frm:pb:pbs:pbsi:selectR');
        var childInputElements = elLength.getElementsByTagName('input');
        var flag = false ;
        for(var i=0; i < childInputElements.length; i++)
        {
            if(childInputElements[i].checked == true)
                {
                    flag = true ;
                    break
                }
        }
        if(!flag)
        {
            alert('Please select one Picture') ;
            return false ;
        }
        else
        {
            Validate() ;
        }
    }
</script>
<apex:form id="frm">
    <apex:actionFunction name="Validate" action="{!SaveImage}" onComplete="alert('Picture is Applied'); window.close();" reRender=""/>
    <apex:pageBlock id="pb" title="Contact" tabStyle="Contact">

        <apex:pageBlockButtons >
            <apex:commandButton rendered="{!IF(Items.size > 0 , true , false)}" value="Save" onClick="return validateRadio() ;"/>
            <apex:commandButton value="Cancel" onClick="window.close() ;"/>
        </apex:pageBlockButtons>

        <apex:pageBlockSection id="pbs" title="All Images" rendered="{!IF(Items.size > 0 , true , false)}">
            <apex:pageBlockSectionItem id="pbsi">
                <apex:selectRadio id="selectR" value="{!selectedImage}">
                    <apex:selectOptions id="MyRadio" value="{!Items}" />
                </apex:selectRadio>
            </apex:pageBlockSectionItem>
        </apex:pageBlockSection>

        <apex:pageBlockSection rendered="{!IF(Items.size > 0 , false , true)}">
            <apex:outputLabel value="No attachments to display or there is no valid image in attachments."/>
        </apex:pageBlockSection>

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


5) Create a Detail Page button with Label : "Set Profile Picture" and Name : "Set_Profile_Picture", Behavior : "Execute Java Script" and Content Source : "OnClick JavaScript"
window.showModalDialog('/apex/DisplayImages?Id={!Contact.Id}','') ; 
window.location.href = window.location.href ;


6) Edit the contact layout and add "Set Profile Picture" button.


7) Create a contact and add some images in notes and attachments, click on "Set Profile Picture". Select the image and click save.


*Note : I hate using JS with IE.


Also you may have to change a line of the Apex code above : "https://c.ap1.content.force.com/servlet/servlet.FileDownload?file=' + selectedImage ;"


in "SaveImage()" method.


Above path can be different on different organizations, so you just need to make sure that this is correct by :
View the attachment uploaded and copy the path from the URL except the ID.You can also create a custom setting to store this path.


Once above steps are done we are all set to go.


Cheers.

Jun 19, 2011

Summer 11 Features - Part 2 (JavaScript Remoting)

One of the major enhancements from visualforce this release(Summer 11) and my favorite is JavaScript remoting.


JavaScript Remoting is the ability to invoke apex class method from javascript embedded in a visualforce page. JavaScript Remoting is now available after summer 11 release.


Here is a quick example : we have a Apex class which defines a get Account method.
global with sharing class MyJSRemoting
{
    public static Account account { get; set; }
     
    @RemoteAction
    global static Account getAccount(String accountName) {
        account = [select id, name, phone, type, numberofemployees from 
             Account where name = :accountName limit 1];
        return account;
    }   
}
This method is having @RemoteAction annotation making it available to be called from a visualforce page. Now in our visualforce page we have a script tag set which is how we embed javascript within visualforce pages.




    
    
    
    
    
        
    
            
                 
            
    
            
                
            
    
        
    


This JavaScript code then invokes the getAccount method in the apex class to take action.


Please note I have used namespace "ankit.MyJSRemoting" as there is a namespace registered on my organization.

JavaScript Remoting is the feature which is primarily be used by developers and will allow them to create richer and more interactive user interfaces that everyone will benefit from.

In particular, lets developers create rich javascript based user interfaces by invoking apex controller methods within JavaScript code. JavaScript is typically used to render small parts of user interface. Result from a Javascript remoting call are much faster then using a typical visualforce reRender model, developers can provide more instant feedback to the user. This is because remoting calls are stateless. Means only data is set back and forth instead a lot of bulky HTML.

Additional Visualforce enhancements :

1) Filtered Lookup via Visualforce.
2) Inline editing for rich text area field.
3) Field Set property accessors.

Summer 11 Features - Part 1 (Enhanced Profile User Interface)

Enhanced Profile User Interface brings a new way of creating, editing and viewing user profiles. Existing profile interface groups together settings and permission by type in a long scrolling detail page for example page layout assignment for all object are grouped in one section, field level security settings in another and object permissions in another. This involves a lot of scrolling and visits to modify multiple sections.


How to enable "Enhanced Profile User Interface" : Set Up > App Set Up > Customize > User Interface > Check "Enable Enhanced Profile User Interface"




Enabling enhanced profile user interface addresses these limitations which provides a clean overview page from where you can easily access the setting and permissions you need.


For example "Find Setting" box at the top let you quickly find the objects tabs and permissions you want to view or modify.




Similarly "Apps" and "System" section have different gain grounds.





Key benefits of enhanced profile user interface :


1) Quickly find individual settings and permissions (Using Find Settings at top)
2) Easily set up profiles for users with a particular job role.
3) Quickly modify settings and permissions for new custom objects


Cheers

Jun 14, 2011

Visualforce Code Generator

We know how much important role visualforce plays in our application. There are many instance where we need to create a visualforce page and apex class. Salesforce provides powerful tools like workflows, approvals, validation etc. from which we can implement our business functionalities with just button clicks.


Now I was having a requirement where I need to create many visualforce pages, some are custom and some are cloning native page with native layouts with some small changes. This just clicked me to create a tool from which we can create a visualforce page code with just clicking buttons. Yes!! Visualforce page code with button click.


This saved a lot of time, as I do not need to write any thing to create a heavy visualforce page and amazingly it is done just using button clicks.


Install the package : https://login.salesforce.com/packaging/installPackage.apexp?p0=04t90000000Pqos


Just append "/apex/vfgenerator__codegenerator" in URL.


Now let me jump into the explanation what exactly I have done. A simple UI will be displayed, where user can select the desired type of page, object name, record type, email field.






Object Name : Valid object API name (include namespace if any)
Record Type : Record type Id of object selected in Object Name
Type of Page :


  1. Edit : Code will be generated for the edit page of the object (according to "record type" layout if selected any).
  2. Detail : Code will be generated for the detail page of the object (according to "record type" layout if selected any)
  3. Custom Detail : Code will be generated for detail page according to the fields selected from UI
  4. Custom Edit : Code will be generated for edit page according to the fields selected from UI
In the above screen I have selected "Edit" as the type of page and "Account" in object, also provided my email. When I click "Generate Code" it displays like this :


Just copy the code and paste it in new visualforce page. Why I have given my email id because when you paste the code in visualforce page it will loose all the formatting and will display in one single line, but code sent on email will come with formatting. So we can copy the generated code from email also. Now when you hit the newly created visualforce page it will display all fields in edit mode which are displayed on native edit page. Isn't that good?

Now lets try creating some custom visualforce page. Select "Custom Edit" in "Type of Page" and "Account" in "Object Name". It will display a section "Select Fields". Click on "Display Fields", it will display all fields which are up datable by present user.



Select some fields and click on  "Generate Code". Again copy paste the code in your visualforce page, it will display selected fields in edit mode.

Now heavy visualforce pages are created with just button clicks.

Package provided is managed because the tool is under testing and I would like to have feedback from you. Once it is free from all bugs I will provide the code.


Declaration: You may find similar post related to "Visualforce Code Generator". The end result may be similar but there is a considerable difference in the approaches being followed here. So I, hereby declare that my project is entirely my own creation and has not been copied from any other person/organization's words or idea. Please feel free to drop me an email at "arora.salesforce@gmail.com" if there is any disagreement.

Cheers

Jun 12, 2011

Using REGEX in Validations

Recently I saw many questions on Discussion Boards regarding validations. Folks always want to go with validations avoiding Apex.


We can not ignore flexibility provided by Apex but I always prefer Validation when I can implement my business logics with it. I am bit lazy kind of person and hate writing test methods, that's why I use validation because if there is no code then no test method. Thanks to Salesforce for providing these kind of native functionalities where I do not have to write any code.


I am going bit off track as there is no point discussing over this. So coming back to REGEX in Validations, I have some good examples.


Example 1 : Validate Credit Card Number
Description :
Validates that a custom text field called Credit_Card_Number is formatted in 9999-9999-9999-9999 or 9999999999999999 number format when it is not blank.The pattern specifies:
• Four digits (0-9) followed by a dash: \\d{4}-
• The aforementioned pattern is repeated three times by wrapping it in () {3}
• Four digits (0-9)
• The OR character (|) allows an alternative pattern of 16 digits of zero through nine with no dashes: \\d{16}


Validation Formula :
NOT( REGEX( Credit_Card_Number__c ,
"(((\\d{4}-){3}\\d{4})|\\d{16})?"))
Error Message : Credit Card Number must be in this format: 9999-9999-9999-9999 or 9999999999999999.


Example 2 : Valid IP Address
Description :
Ensures that a custom field called IP Address is in the correct format, four 3-digit numbers (0-255) separated  by periods.

Validation Formula :
NOT(
REGEX( IP_Address__c,
"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
))
Error Message : IP Address must be in form 999.999.999.999 where each part is between 0 and 255.


Example 3 : US Phone Number Has Ten Digits
Description :
Validates that the Phone number is in (999) 999-9999 format. This works by using the

REGEX function to check that the number has ten digits in the (999) 999-9999 format.


Validation Formula : 
NOT(REGEX(Phone, "\\D*?(\\d\\D*?){10}"))
Error Message : US phone numbers should be in this format: (999) 999-9999.


Example 4 : Social Security Number Format
Description :
Validates that a custom text field called SSN is formatted in 999-99-9999 number format

(if it is not blank). The pattern specifies:
• Three single digits (0-9):\\d{3}
• A dash
• Two single digits (0-9):\\d{2}
• A dash
• Four single digits (0-9):\\d{4}


Validation Formula :
NOT(
OR(
LEN (Social_Security_Number__c) = 0,
REGEX( Social_Security_Number__c , "[0-9]{3}-[0-9]{2}-[0-9]{4}")
))
Error Message : SSN must be in this format: 999-99-9999.


This will provide am idea how we can write validations using REGEX.


Cheers.



Jun 4, 2011

Math.Round Utility in Salesforce

Now rounding your number to desired decimal value is no longer a headache.


How?????


Just use the below method and pass your decimal number as first parameter and the decimal places as second parameter. 
public Decimal roundNumber(Decimal roundNumber , Integer decimalPlace)
    {
        if(roundNumber != null)
        {
            Decimal decPlace = Math.POW(10 , decimalPlace) ;
            return Math.round(roundNumber * decPlace) / decPlace ;
        }
        else
        {
            return 0 ;
        }
    }


Presently salesforce provides Math.Round(your_number) which will return the number after rounding with no decimal values.


For example : If I do this
System.debug('Rounded number : ' + Math.Round(2.333454)) ;


It will return Round Number : 2


I don't find way to get number round with two decimal places like in this case if I want the number to be rounded with two decimal places then it should return 2.33


Above method makes it pretty simple, we only need to pass decimal value and the decimal places in method like this :
Decimal num = roundNumber(1.567 , 2) ;
System.debug('num ::::: ' + num) ;
It will return 1.57


Also another way to round number by decimal places is :
Decimal d = 1.426 ;
Double num = d.setScale(2) ;
System.debug('num ::::::::::::: ' + num) ;


Cheers
Feedbacks are always welcomed