Building Visualforce pages for Standard Pages : Part 1 – Account Edit Page

Building Visualforce pages for Standard Pages : Part 1 – Account Edit Page
Building Visualforce pages for Standard Pages : Part 2 – Contact Edit Page
Building Visualforce pages for Standard Pages : Part 3 – Case Edit Page

Most Salesforce implementations start with leveraging standard functionality, and start moving to custom Visualforce pages down the road. One of the commonly encountered tasks is to build a Visualforce page instead of a standard page, so you could build some custom functionality. Through this series of articles, I will try to give you templates of Visualforce pages that mimic the behavior of the Standard pages. You can build further custom functionality on top of this.

Steps to use this template
1.
Create a Visualforce page (I used the name “AccountEdit”), and copy all the code below.
2. Save the page, and test it by visiting the URL below, making sure to pass an existing account ID as a parameter (refer to my article here if you are fuzzy about Salesforce URLs)  :-

https://{your org}.visual.force.com/apex/AccountEdit?id=001E000000KC75q&retURL=%2F001E000000KC75q

3. Create a custom “Edit” button for Account, that takes you to this page when clicked.

That’s it, you now have a custom visualforce page that looks exactly like the standard account edit page.

Be sure to read the “gotchas” at the end of the code snippet to get a list of potential issues.

Code Snippet
<apex:page standardController="Account" showHeader="true" sidebar="true">
    <apex:form id="myForm">
        <script>
            function copyAddress() {
                var shippingStreet = document.getElementById('j_id0:myForm:pgBlock:pgBlockSectionAddressInfo:j_id58:actShippingStreet');
                var shippingCity = document.getElementById('j_id0:myForm:pgBlock:pgBlockSectionAddressInfo:j_id64:actShippingCity');
                var shippingState = document.getElementById('j_id0:myForm:pgBlock:pgBlockSectionAddressInfo:j_id70:actShippingState');
                var shippingCountry = document.getElementById('j_id0:myForm:pgBlock:pgBlockSectionAddressInfo:j_id82:actShippingCountry');
                var shippingPostalCode = document.getElementById('j_id0:myForm:pgBlock:pgBlockSectionAddressInfo:j_id76:actShippingPostalCode');

                var BillingStreet = document.getElementById('j_id0:myForm:pgBlock:pgBlockSectionAddressInfo:j_id55:actBillingStreet');
                var BillingCity = document.getElementById('j_id0:myForm:pgBlock:pgBlockSectionAddressInfo:j_id61:actBillingCity');
                var BillingState = document.getElementById('j_id0:myForm:pgBlock:pgBlockSectionAddressInfo:j_id67:actBillingState');
                var BillingCountry = document.getElementById('j_id0:myForm:pgBlock:pgBlockSectionAddressInfo:j_id79:actBillingCountry');
                var BillingPostalCode = document.getElementById('j_id0:myForm:pgBlock:pgBlockSectionAddressInfo:j_id73:actBillingPostalCode');

                shippingStreet.value = BillingStreet.value;
                shippingCity.value = BillingCity.value;
                shippingState.value = BillingState.value;
                shippingCountry.value = BillingCountry.value;
                shippingPostalCode.value = BillingPostalCode.value;

            }
        </script>
        <apex:sectionHeader title="Account Edit" subtitle="{!Account.Name}" />   
        <apex:pageBlock id="pgBlock" mode="edit" title="Account Edit">
            <apex:pageBlockButtons location="both">
                <apex:commandButton value="Save" action="{!Save}"/>
                <apex:commandButton value="Cancel" action="{!Cancel}"/>
            </apex:pageBlockButtons>
        <apex:pageBlockSection id="pgBlockSectionAcctInfo" title="Account Information" collapsible="false" columns="2" >
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Account Owner</apex:outputLabel>
                <apex:outputField id="actOwner" value="{!account.ownerid}" />
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Rating</apex:outputLabel>
                <apex:inputField id="actRating" value="{!account.rating}" />
            </apex:pageBlockSectionItem>
           
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Account Name</apex:outputLabel>
                <apex:inputField id="actName" value="{!account.name}" required="true" />
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Phone</apex:outputLabel>
                <apex:inputField id="actPhone" value="{!account.Phone}" />
            </apex:pageBlockSectionItem>   
           
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Parent Account</apex:outputLabel>
                <apex:inputField id="actParentAccount" value="{!account.ParentId}" />
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Fax</apex:outputLabel>
                <apex:inputField id="actFax" value="{!account.Fax}" />
            </apex:pageBlockSectionItem>    
           
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Account Number</apex:outputLabel>
                <apex:inputField id="actNumber" value="{!account.Accountnumber}" />
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Website</apex:outputLabel>
                <apex:inputField id="actWebsite" value="{!account.Website}" />
            </apex:pageBlockSectionItem>
           
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Account Site</apex:outputLabel>
                <apex:inputField id="actSite" value="{!account.Site}" />
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Ticker Symbol</apex:outputLabel>
                <apex:inputField id="actTicker" value="{!account.TickerSymbol}" />
            </apex:pageBlockSectionItem>
           
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Type</apex:outputLabel>
                <apex:inputField id="actType" value="{!account.Type}" />
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Ownership</apex:outputLabel>
                <apex:inputField id="actOwnership" value="{!account.Ownership}" />
            </apex:pageBlockSectionItem>
           
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Industry</apex:outputLabel>
                <apex:inputField id="actIndustry" value="{!account.Industry}" />
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Employees</apex:outputLabel>
                <apex:inputField id="actEmployees" value="{!account.NumberOfEmployees}" />
            </apex:pageBlockSectionItem>
           
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Annual Revenue</apex:outputLabel>
                <apex:inputField id="actAnnualRevenue" value="{!account.AnnualRevenue}" />
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel >SIC Code</apex:outputLabel>
                <apex:inputField id="actSIC" value="{!account.Sic}" />
            </apex:pageBlockSectionItem>           
        </apex:pageBlockSection>
           
        <apex:pageBlockSection id="pgBlockSectionAddressInfo" title="Address Information" collapsible="false" columns="2">
            <apex:facet name="header">
                    <span class="pbSubExtra">
                        <span class="bodySmall">
                            <a href="javascript:copyAddress();">Copy Billing Address to Shipping Address</a>
                        </span>
                    </span>
                    <h3>Address Information<span class="titleSeparatingColon">:</span></h3>
            </apex:facet>
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Billing Street</apex:outputLabel>
                <apex:inputField id="actBillingStreet" value="{!account.BillingStreet}" />
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Shipping Street</apex:outputLabel>
                <apex:inputField id="actShippingStreet" value="{!account.ShippingStreet}" />
            </apex:pageBlockSectionItem>
           
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Billing City</apex:outputLabel>
                <apex:inputField id="actBillingCity" value="{!account.BillingCity}" />
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Shipping City</apex:outputLabel>
                <apex:inputField id="actShippingCity" value="{!account.ShippingCity}" />
            </apex:pageBlockSectionItem>
           
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Billing State/Province</apex:outputLabel>
                <apex:inputField id="actBillingState" value="{!account.BillingState}" />
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Shipping State/Province</apex:outputLabel>
                <apex:inputField id="actShippingState" value="{!account.ShippingState}" />
            </apex:pageBlockSectionItem>          
           
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Billing Zip/Postal Code</apex:outputLabel>
                <apex:inputField id="actBillingPostalCode" value="{!account.BillingPostalCode}" />
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Shipping Zip/Postal Code</apex:outputLabel>
                <apex:inputField id="actShippingPostalCode" value="{!account.ShippingPostalCode}" />
            </apex:pageBlockSectionItem>   
           
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Billing Country</apex:outputLabel>
                <apex:inputField id="actBillingCountry" value="{!account.BillingCountry}" />
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                <apex:outputLabel >Shipping Country</apex:outputLabel>
                <apex:inputField id="actShippingCountry" value="{!account.ShippingCountry}" />
            </apex:pageBlockSectionItem>
           
        </apex:pageBlockSection>
        <apex:pageBlockSection id="pgBlockSectionAdditionalInformation" title="Additional Information" collapsible="false" columns="2">
            <!--ANY CUSTOM FIELDS / ADDITIONAL INFORMATION CAN GO HERE-->
        </apex:pageBlockSection>
    </apex:pageBlock>
    </apex:form>
</apex:page>

Gotchas
* Check out the “copyAddress” javascript function at the top – this function does the job of copying the billing address to the shipping address on clicking the “Copy Billing Address to Shipping Address” link.
* Make sure that the IDs of all the textboxes (billingstreet, shippingstreet etc.) being used in the function are the correct IDs – I have highlighted these IDs in the javascript. If you customize this page to add more fields, the IDs will change, and you will have to fix the javascript to use the correct IDs. You can look at the page HTML source to figure out the IDs, or you can refer to this article to know how to get the ID for a field.

So there you go – you can now use this code to build a basic account edit page, that exactly mimics everything in the standard functionality.

10 comments:

  1. i want only address fields and to copy that link. but in this code if i remove remaining fields then functionality is not working. How to achieve this?

    ReplyDelete
  2. Hmm, were you able to verify that the code works as is ? maybe the IDs on your page are different from that in the code, so nothing might actually be working.

    Check if the code works properly with all the fields, then start removing one by one.

    ReplyDelete
  3. Let me start by saying I have no real idea what I am doing when it comes to writing javascript code. I was wondering if I could use a portion of this code to create a button on the opportunity without having to create the visual force page. Basically just wanting to copy mailing address information to the billing address information without having to retype.

    ReplyDelete
    Replies
    1. Well, short answer is, No. The reason is that there is no way to "customize" the "edit" pages for salesforce objects. You can customize the standard pages using "customize page layout", but when it comes to the edit pages, the only option is to build your own Visual force page.

      I'd encourage you to try and create the VF page for opportunity. It should be similar to what I have posted here for Account.

      Delete
  4. Ok, I will look into that. Hopefully it is not as scary as it sounds.

    ReplyDelete
  5. Nope, it's not. Try creating a custom VF page for account edit by copy-pasting the code here. Let me know if you run into issues.

    ReplyDelete
  6. regarding maintenance, Do I need to edit the fields down the layout every time I add a field to Account Layout or no, since we are still in Dev phase, this happens a lot.

    ReplyDelete
  7. Hi Saurabh,

    Nice write up.. working

    Can I implement this in standard layout?

    Thanks,
    Hitesh N Patel

    ReplyDelete
  8. What does j_idX, represent here?

    ReplyDelete
  9. These are the IDs for each element - for e.g., the shipping street textbox on the page has an ID of j_id0:myForm:pgBlock:pgBlockSectionAddressInfo:j_id58:actShippingStreet.

    You can check out the IDs by viewing the page source .... (on chrome), right click --> View page source.

    ReplyDelete