Override a standard Salesforce page layout with VisualForce
Ok, first I would like to say this is my first post for you. This post can be perceived as very basic to some and very complex to others, so if creating a VisualForce page with a Standard controller (no APEX) isn’t for you, don’t worry. I’m pretty sure I’ll have some APEX for you soon.
I assume you will already have a Developer org. If you don’t you can pick up a free one here: http://www.developerforce.com/events/regular/registration.php?d=70130000000EjHb
Now, back to topic. Since we want to override a Standard SalesForce page we need to choose an object who’s page we want to override first. I’ve chosen the Leads Object for this tutorial.
Before we begin you may want to enable Development Mode. SalesForce has a page that will show you how to do this. Click here for this page.
A simple use case for overriding the Lead page with a new VisualForce page might be:
Your company would like to allow its users to choose Lead owners when they Create or Edit Leads in the system. By default the owner field is set to the user who creates the lead.
Essentially what we are doing is “Overriding” the “Out of Box” (A.K.A OOB) Lead Page. In order to override this page we must create a new page to use for this override.
There are a few ways to go about creating a VisualForce page, but today I’m only going to show you how to create this page through the SalesForce.com Setup page. To create a new VisualForce page go to “Your Name” > Setup > Develop > Pages and click the New button.
You will now see the VisualForce page creation wizard. The very first thing you will want to do is give your new VisualForce page a Label. A label is a more esthetic name of what your page name will actually be. For this tutorial let’s use “Lead Override”.
Once you’ve typed your page label press the Tab key to set your cursor to the Name field. You will notice that the Name automatically took the value of “Lead Override” from Label. SalesForce won’t allow you to have spaces in the name so replace your space with an Underscore character as shown below.
SalesForce will automatically give you some default VisualForce markup to work with as shown below.
<apex:page> <!-- Begin Default Content REMOVE THIS --> <h1>Congratulations</h1> This is your new Page <!-- End Default Content REMOVE THIS --> </apex:page>
We actually do not need most of this code for this tutorial so select all of the text in between the apex:page tags and press your Delete/Backspace key on your keyboard.
We’re now left with two apex:page tags (one beginning tag and one closing tag) as shown below.
<apex:page> </apex:page>
These tags should exist in EVERY VisualForce page you will create. You will always have a beginning <apex:page> tag at the top of your page and a closing </apex:page> tag at the bottom of your page. Consider these tags to be boundaries. All of the VisualForce, HTML and Javascript you create will lay between these tags.
The next tag we will create is called the apex:form tag. This tag is in virtually every VisualForce page you will create. In Spring ’12 you can now have more than one apex:form tag however that is well beyond the scope of this tutorial and in fact discouraged from the documentation. So at this point just know that 99% of the time when you are creating a VisualForce page the very next tag after your apex:page tag should be an apex:form tag.
Lets create this now.
Type your beginning and closing apex:form tags in between the apex:page tags as shown below.
<apex:page> <apex:form> </apex:form> </apex:page>
The apex:form tag is the tag that is used to actually submit your form fields to SalesForce for processing. Without it, the data the user typed inside these fields would go nowhere when the user pressed the save button. Not to mention that SalesForce won’t allow you to create fields in a VisualForce page without an apex:form tag anyway :).
Our code is coming along however SalesForce still doesn’t know that this form should be saving Lead data. Lets tell our Page that we want to use SalesForce’s Standard functionality (no APEX code) to process the Lead objects data when our Lead page is saved.
To do this we need to add a couple Attributes to the opening apex:page tag. The first Attribute we’ll set is the StandardController Attribute. This Attribute will allow us to tell the page we want to use SalesForce’s standard functionality on a specific object we choose. The second Attribute we will want to set is the tabStyle. This will tell SalesForce to use the decorative style sheet (CSS A.K.A Cascading Style Sheet) for the Lead object. These two Attributes are shown below.
<apex:page standardcontroller="Lead" tabstyle="Lead"> <apex:form> </apex:form> </apex:page>
Ok, our page is now setup with its StandardController. Ideally at this point you would like to see what your page looks like right? Well unfortunately what we have done so far is invisible to us at the moment for two reasons:
- Page and Form tags are invisible.
- We haven’t setup our SalesForce instance to use this VisualForce page rather than the OOB lead page when a user clicks the New or Edit button.
In this next section we’re going to add a couple more items to our page so we can see something when the page is run as well as hook up the New and Edit buttons on the Lead object so it will display our new VisualForce page.
Add the following text in-between the apex:form tags
<apex:sectionheader title="Lead Edit" subtitle="{!if(Lead.Id==null,'New Lead',Lead.Name)}"></apex:sectionheader>
Then add Hello World, this is my new visualforce page! directly below. The full code should look like below
<apex:page standardcontroller="Lead" tabstyle="Lead"> <apex:form> <apex:sectionheader title="Lead Edit" subtitle="{!if(Lead.Id==null,'New Lead',Lead.Name)}"></apex:sectionheader> Hello World, this is my new visualforce page! </apex:form> </apex:page>
Before we hook our page up with SalesForce I’d like to explain what we’ve just done. The first tag you just setup is called a sectionHeader. This gives us a nice looking header to our page. I’ve set up two attributes to this sectionHeader. The “title” attribute displays above the “subtitle”. You won’t see this now, but oddly enough subtitle will display LARGER than title. This goes against instinct on how title and subtitle work, but nonetheless this is how SalesForce works.
You will see that in the subtitle attribute we’ve added a formula in-between two curly brackets and an exclamation point: {! FORMULA }. Any type of calculation done on the Force.com platform that can be returned ie: variable, formula, field, etc. must be placed in-between the curly brackets and the exclamation point. The Force.com platform will look for these brackets and exclamation and try to process the data between them. In VisualForce you are allowed to place these virtually anywhere within the page.
In this specific formula we simply say: If this Lead is New then display “New Lead” If not New then Display “The Name of the Lead”. Now there may be a better way to check if the record is new, but it’s just as easy to check if the record has an Id (Identifier) or not. New records in SalesForce do not have an Id unless the record has been saved to the database. Once the record is saved to the database, the system will generate a unique Id for the record. We’re are getting a little off the beaten path here so let’s get back to discussing the text between the apex:form tags…
So we talked about the apex:sectionHeader, but now you have this “Hello World…” text that is not embedded in a tag like we’ve been placing in attributes thus far. This is because VisualForce also supports HTML and standard text. VisualForce pages don’t have to be just about VisualForce tags.
When our page is displayed you will see a nice looking Lead header along with the text: “Hello World, this is my new visualforce page!”.
Go ahead and save your page and let’s go hook up our page up to the New and Edit buttons!
Here is the clickpath to the Lead Objects Buttons and Links page. Please navigate to: “Your Name” > Setup > Customize > Leads > Buttons and Links
Now setup your New and Edit Button so it uses our new Lead_Override page as shown below.
Now that your page is all hooked up let’s go ahead and run a test. Go and try to create a new lead. You should end up with a page that looks like this
Looks good right? Not exactly what you wanted, I know. Lets clear out that “Hello World…” text and start adding some VisualForce that will allow us to start entering in some data.
Back in your code where you removed the “Hello World…” line of text let’s place this new tag (New Tag refers to a new tag you are learning vs a new tag to Spring ’12)
<apex:pageblock mode="edit" id="leadPB" title="Lead Edit">
This tag allows us to group a set of tags within a certain style we are trying to achieve. In this case we want the “mode” of our page to be treated as an “edit” page with the title set to “Lead Edit”.
As we discussed before, every tag you create you must also have a closing tag. Add this closing tag below your new pageBlock
<apex:pageblock></apex:pageblock>
Go ahead now and save your page then try to create a new lead again. You’ll now end up with a box within your page titled: “Lead Edit” as shown below.
In order to Save our Lead we will need some fields and buttons. Lets start off with adding a Save and Cancel button. To create buttons that run stadnardController functions like Save and Cancel we need to use the apex:pageBlockButtons and apex:commandButton tags. The apex:pageBlockButtons tag will create an area where our apex:commandButton tags (Save and Cancel buttons) will exists. In your code add the following section in between your pageBlock tags you created earlier.
<apex:pageblockbuttons> <apex:commandbutton action="{!save}" value="Save"></apex:commandbutton> <!-- If you wish to implement Save & New functionality you will have to write an apex Extension with your own Save & New Method --> <apex:commandbutton action="{!cancel}" value="Cancel"></apex:commandbutton> </apex:pageblockbuttons>
You will notice some new tags you may not have seen before starting with “<!–” and ending with “–>”. These are HTML Comment tags. Comment tags are used when you want to add some helper text so you or other developers can communicate messages about your code or maybe why you chose a certain implementation vs another.
In this example I’m explaining that since we are creating a VisualForce page to override the OOB Lead page, we will lose the functionality of the “Save & New” button that exists on the OOB Page Layout. Since StandardControllers do not have “Save & New” functionality you would have to create your own Extension written in APEX with a new method called something like SaveAndNew(). Custom Extensions are beyond the scope of this tutorial.
In each commandButton we just inserted into the VisualForce page you will notice a new Attribute called “action”. Since we are using a StandardController we only have access to very specific actions such as Save and Cancel. If you place anything that is unacceptable by the StandardController your page will throw an error when you try to save your VisualForce page. For a full list of actions that a StandardController accepts click here.
If you’d like go ahead and save your page and test a new lead to see what your page looks like. You will end up with two buttons at the top of your page. I’ll refrain from showing an image of this section. I think by now you should get the feel for saving and viewing your progress. Let’s move on to adding some more tags and fields.
Add this tag to your document just under your pageBlockButtons closing tag
<apex:pagemessages></apex:pagemessages> <!-- displays all message generated by the component -->
This new tag is used to display any errors that occur during a page save (ie: a user did not enter a required field then saved the page).
Without this generic tag users will not see errors should they encounter any during the saving of a record.
Here is our first section of fields. I’m going to enter the entire pageBlock of fields and then briefly explain some of the details behind our implementation. Either copy and paste or write this directly below your apex:pagemessages tag.
<apex:pageblocksection id="LeadInformationPBS" title="Lead Information"> <!-- Make Owner field editable --> <apex:inputfield value="{!Lead.OwnerId}"></apex:inputfield> <apex:inputfield value="{!Lead.Phone}"></apex:inputfield> <!-- Since we need to group two input fields together we need a pageBlockSectionItem with an Output panel. We also needed to create a label so we know what field we are entering in --> <apex:pageblocksectionitem> <apex:outputlabel value="{!$ObjectType.Lead.Fields.FirstName.label}"></apex:outputlabel> <apex:outputpanel> <apex:inputfield value="{!Lead.Salutation}"></apex:inputfield> <apex:inputfield value="{!Lead.FirstName}"></apex:inputfield> </apex:outputpanel> </apex:pageblocksectionitem> <apex:inputfield value="{!Lead.MobilePhone}"></apex:inputfield> <apex:inputfield value="{!Lead.LastName}"></apex:inputfield> <apex:inputfield value="{!Lead.Fax}"></apex:inputfield> <apex:inputField value="{!Lead.Company}" /> <apex:inputfield value="{!Lead.Email}" required="true"></apex:inputfield> <apex:inputfield value="{!Lead.Title}"></apex:inputfield> <apex:inputfield value="{!Lead.Website}"></apex:inputfield> <apex:inputfield value="{!Lead.Leadsource}"></apex:inputfield> <apex:inputfield value="{!Lead.Status}"></apex:inputfield> <!-- <apex:inputField value="{!Lead.Campaign}" /> Campaign field is not able to be used unless you write your own custom class/method to create a campaign member Post explaining this issue: http://boards.developerforce.com/t5/Apex-Code-Development/Cannot-Access-to-Campaign-Field-from-Lead-Object/td-p/161715 --> <apex:inputfield value="{!Lead.Rating}"></apex:inputfield> <apex:inputfield value="{!Lead.Industry}"></apex:inputfield> <apex:inputfield value="{!Lead.NumberOfEmployees}"></apex:inputfield> </apex:pageblocksection>
Starting from top to bottom we have our first tag which is an apex:pageBlockSection. This tag will allow you to group tags together under a header that you set the title for. This pageBlockSection is for our Lead Information section which we’ve set our “title” Attribute to.
You will also notice I’ve set the “id” Attribute. We will not go to deep into this attribute, but I would recommend setting your own “id” attributes in your tags. These ids can be anything you choose, but they must be unique meaning, no other tag can contain the same id. This allows us to reference these fields with technologies such as JavaScript or JQuery.
Our next two tags are called apex:inputFields. apex:inputFields are the actual input fields your users will type their data into. Your VisualForce page will take the input of these fields and save it to the database. You will notice that the “value” attribute will contain the actual object field you wish the user to enter.
Now it’s important to note that these fields will be displayed left to right rather than top to bottom in a 2 column grouping by default. So for example if you want Phone under Owner you will need to place either a space after Owner or another fields to shift the Phone field under owner.
The next section is a little bit trickier. The OOB Lead Page Layout allowed us to choose a Salutation along with the Lead’s First Name in one group.
To do this we need to create a pageBlockSectionItem to hold a Label for our group of fields along with the fields themselves. There is one issue with this; the pageBlockSectionItem tag only accepts 2 tags max. We have 3 (1 Label and 2 Fields). What we’ve done here is “tricked” our pageBlockSection item into thinking there are only 2 tags. We did this by wrapping the two apex:inputFields into a new tag called apex:outputPanel. The pageBlockSection item is now only counting the Label and the Output panel as items it contains.
Since we are using a pageBlockSectionItem we actually lose some functionality given to us when just using a regular apex:inputField by itself. One of these bits of functionality we lose is the Label. pageBlockSectionItems do not come with a label so we are using a new tag called apex:outputlabel to display our label. You are allowed to set any text you wish as the “value” attribute. Rather than setting this text to “FirstName” I’ve found it best to reach into the object’s field itself and pull this label from the system.
You can do this with any field by using the following snippet: {!$ObjectType.OBJECT_YOU_ARE_PULLING_FROM.Fields.FIELD_NAME.label} where OBJECT_YOU_ARE_PULLING_FROM is any object such as “Lead” and FIELD_NAME is any field on that object such as “FirstName”.
Now I believe the rest of these fields should be self explanatory however I do want to mention one thing; I’ve decided it’s best to show you how to make a field “Required”. If you notice, our Email field has an Attribute called “required” and it’s set to true. Do this in your VisualForce page whenever a field is required yet its field level security is not set to required.
I’ve added a few comments in this code that you should read over. It’s imperative that you understand that by choosing to Override a VisualForce page on a Standard OOB SalesForce object that you are waving your rights to certain functions that SalesForce gives you by default. I’ve mentioned the loss of “Save & New” already, but you will also be missing the ability to add this Lead to Campaign members as well as missing the ability to set wether you want to use Active Assign Rules or not.
At this point I think it’s time to take off the training wheels and give you the remaining code to build your page. I will also add the full code at the very bottom so you can compare what you have vs. what the full page looks like for this tutorial.
Add this code directly beneath your last apex:pageBlockSection
<apex:pageblocksection id="AddressInformationPBS" title="Address Information"> <apex:inputfield value="{!Lead.Street}"></apex:inputfield> <apex:outputtext value=""></apex:outputtext> <apex:inputfield value="{!Lead.City}"></apex:inputfield> <apex:outputtext value=""></apex:outputtext> <apex:inputfield value="{!Lead.State}"></apex:inputfield> <apex:outputtext value=""></apex:outputtext> <apex:inputfield value="{!Lead.PostalCode}"></apex:inputfield> <apex:outputtext value=""></apex:outputtext> <apex:inputfield value="{!Lead.Country}"></apex:inputfield> <apex:outputtext value=""></apex:outputtext> <!-- Don't Really need to implement this extra space, but it's not bad practice --> </apex:pageblocksection> <apex:pageblocksection id="AdditionalInformationPBS" title="Additional Information"> <apex:inputfield value="{!Lead.ProductInterest__c}"></apex:inputfield> <apex:inputfield value="{!Lead.CurrentGenerators__c}"></apex:inputfield> <apex:inputfield value="{!Lead.SICCode__c}"></apex:inputfield> <apex:inputfield value="{!Lead.Primary__c}"></apex:inputfield> <apex:inputfield value="{!Lead.NumberofLocations__c}"></apex:inputfield> </apex:pageblocksection> <apex:pageblocksection id="DescriptionInformationPBS" title="DescriptionInformation"> <apex:inputfield value="{!Lead.Description}"></apex:inputfield> </apex:pageblocksection> <apex:pageblocksection id="OptionPBS" title="Lead Information"> <!-- If you want to have a checkbox to implement whether to use Active Assignment rules you will need to create your own using a custom Apex Extension and method --> Here we can place any extra fields or lead options we wish... </apex:pageblocksection>
One thing I did not explain yet is you can insert “Blank Spaces” into your layout to shift fields around to your liking. To do this you use the outputText tag with nothing in-between the double quotes for the value Attribute as shown below.
<apex:outputtext value=""></apex:outputtext>
Note: It’s not required, but its best practice to close any tags that do not contain data in-between so its one tag vs. two. The above example would look like this
<apex:outputtext value="" />
Ok, now go ahead, save your page and see what it looks like!
You should end up with a very similar if not exact page that looks like this:
That wraps up this tutorial. I wasn’t too sure how to break up this tutorial as it covers so much so thanks for bearing with me!
Below is the complete VisualForce markup for this tutorial. Feel free to use this as a start and follow the tutorial again incase you missed anything on the first go around. I’d also like to recommend checking out the VisualForce Developers Guide located here: http://www.salesforce.com/us/developer/docs/pages/salesforce_pages_developers_guide.pdf
<apex:page standardcontroller="Lead" tabstyle="Lead"> <apex:form> <apex:sectionheader title="Lead Edit" subtitle="{!if(Lead.Id==null,'New Lead',Lead.Name)}"></apex:sectionheader> <apex:pageblock mode="edit" id="leadPB" title="Lead Edit"> <apex:pageblockbuttons> <apex:commandbutton action="{!save}" value="Save"></apex:commandbutton> <!-- If you wish to implement Save & New functionality you will have to write an Apex Extension with your own Save & New Method --> <apex:commandbutton action="{!cancel}" value="Cancel"></apex:commandbutton> </apex:pageblockbuttons> <apex:pagemessages></apex:pagemessages> <!-- displays all message generated by the component --> <apex:pageblocksection id="LeadInformationPBS" title="Lead Information"> <!-- Make Owner field editable in system or else you won't be able to edit the Owner --> <apex:inputfield value="{!Lead.OwnerId}"></apex:inputfield> <apex:inputfield value="{!Lead.Phone}"></apex:inputfield> <!-- Since we need to group two input fields together we need a pageBlockSectionItem with an Output panel. We also needed to create a label so we know what field we are entering in --> <apex:pageblocksectionitem> <apex:outputlabel value="{!$ObjectType.Lead.Fields.FirstName.label}"></apex:outputlabel> <apex:outputpanel> <apex:inputfield value="{!Lead.Salutation}"></apex:inputfield> <apex:inputfield value="{!Lead.FirstName}"></apex:inputfield> </apex:outputpanel> </apex:pageblocksectionitem> <apex:inputfield value="{!Lead.MobilePhone}"></apex:inputfield> <apex:inputfield value="{!Lead.LastName}"></apex:inputfield> <apex:inputfield value="{!Lead.Fax}"></apex:inputfield> <apex:inputField value="{!Lead.Company}" /> <apex:inputfield value="{!Lead.Email}" required="true"></apex:inputfield> <apex:inputfield value="{!Lead.Title}"></apex:inputfield> <apex:inputfield value="{!Lead.Website}"></apex:inputfield> <apex:inputfield value="{!Lead.Leadsource}"></apex:inputfield> <apex:inputfield value="{!Lead.Status}"></apex:inputfield> <!-- <apex:inputField value="{!Lead.Campaign}" /> Campaign field is not able to be used unless you write your own custom class/method to create a campaign member Post explaining this issue: http://boards.developerforce.com/t5/Apex-Code-Development/Cannot-Access-to-Campaign-Field-from-Lead-Object/td-p/161715 --> <apex:inputfield value="{!Lead.Rating}"></apex:inputfield> <apex:inputfield value="{!Lead.Industry}"></apex:inputfield> <apex:inputfield value="{!Lead.NumberOfEmployees}"></apex:inputfield> </apex:pageblocksection> <apex:pageblocksection id="AddressInformationPBS" title="Address Information"> <apex:inputfield value="{!Lead.Street}"></apex:inputfield> <apex:outputtext value=""></apex:outputtext> <apex:inputfield value="{!Lead.City}"></apex:inputfield> <apex:outputtext value=""></apex:outputtext> <apex:inputfield value="{!Lead.State}"></apex:inputfield> <apex:outputtext value=""></apex:outputtext> <apex:inputfield value="{!Lead.PostalCode}"></apex:inputfield> <apex:outputtext value=""></apex:outputtext> <apex:inputfield value="{!Lead.Country}"></apex:inputfield> <apex:outputtext value=""></apex:outputtext> <!-- Don't Really need to implement this extra space, but it's not bad practice --> </apex:pageblocksection> <apex:pageblocksection id="AdditionalInformationPBS" title="Additional Information"> <apex:inputfield value="{!Lead.ProductInterest__c}"></apex:inputfield> <apex:inputfield value="{!Lead.CurrentGenerators__c}"></apex:inputfield> <apex:inputfield value="{!Lead.SICCode__c}"></apex:inputfield> <apex:inputfield value="{!Lead.Primary__c}"></apex:inputfield> <apex:inputfield value="{!Lead.NumberofLocations__c}"></apex:inputfield> </apex:pageblocksection> <apex:pageblocksection id="DescriptionInformationPBS" title="DescriptionInformation"> <apex:inputfield value="{!Lead.Description}"></apex:inputfield> </apex:pageblocksection> <apex:pageblocksection id="OptionPBS" title="Lead Information"> <!-- If you want to have a checkbox to implement whether to use Active Assignment rules you will need to create your own using a custom Apex Extension and method --> Here we can place any extra fields or lead options we wish... </apex:pageblocksection> </apex:pageblock> </apex:form> </apex:page>
Thanks for this! It is a great tutorial and very helpful, and fantastic that you took the time to explain every detail.
Thanks man for providing the recipe i wanted.
Really liked the way you explained everything.. hats off man…
Tom Fuda on August 29, 2008 at 5:32 amFYI, That’s what the SRC button is for in the tool bar of the New Message edtior on the Salesforce. discussion forums. Click that button and insert your source code, and semi-colons will not be treated as smileys
Hi i am new to salesforce please help me out from this, I have VF page to override standard Account “new” button page, In that VF page i have Parent Account field which will get the Lookup to Account Record and another problem is i am not able to retrive billing and shipping address fields , I’m facing problem and can’t able to resolve it.Please help me out from this
Here is my VF page .
VF Page
how to implement the check boxes options –Assign using active assignment rules,Send notification email to contact on case page layout.
Aryan, looks like the page didn’t come through. Try using code tags in the comments.
Chandu, can you elaborate a little more? Trying to get the full picture of what you are looking to do. I think I got it, but want to make sure before I start writing. :)
Now that you’ve created a page to display an account with tabs, you can use this page to override the detail view for all accounts.
Aw, this was an exceptionally good post. Spending some time and actual effort to produce a superb article… but
what can I say… I put things off a whole lot and don’t seem to get nearly anything done.
This is a very helpful post.Solved my problem.Great Help Sir.
Cheers,
Manish
Thank you! This was super helpful and I was easily able to adapt it for a custom object.