Salesforce Custom Convert Lead Page and Lead Conversion Process Using Visualforce and Apex

There are a number of “Black Box” processes in Salesforce that are essentially hardcoded functions that you have little or no control over. The out-of-the-box Lead Conversion process is one of these Black Box processes – when you click the standard ‘Convert’ button from a Lead record, you get redirected to a page called leadconvert.jsp.

While the standard page used for lead conversion is good enough most of the time for most customers, you may eventually find yourself asking, “How do I customize the Convert Lead screen?

We figured the Salesforce community would get value from a customizable lead conversion page and process, so we built one by recreating the Convert Lead page using Visualforce, Javascript, and Apex and published it as an unmanaged package on the AppExchange. By publishing as an unmanaged package, you get full access to the Apex classes, Visualforce pages, and Visualforce components and can customize them to create your own lead conversion process for your Salesforce org.

What are the use cases for a custom Convert Lead page for converting Salesforce leads?

  • Include additional Opportunity, Account or Contact fields when converting a Lead
  • Hide fields on the Convert Lead page
  • Prevent users from creating new Opportunities when converting a Lead
  • Remove the Task fields from the Convert Lead page
  • Include additional custom buttons on the Convert Lead page
  • Add or remove sections and manage the style and formatting of the Convert Lead page
  • Implement custom or complex field mapping logic
  • Map Lead fields to multiple fields on the converted Opportunity, Account or Contact
  • Select an Account or Opportunity Record Type when converting a Lead
  • Redirect to a different object or screen after converting a Lead
  • Include a custom update on the Chatter feeds for converted records
  • Add Products to Opportunities at the time of lead conversion
  • Include logic to set default options and values when converting Leads
  • Copy Lead field values to custom objects upon conversion

How does the custom Convert Lead page work?

We studied how the standard Salesforce Lead conversion process worked from end-to-end, and built an exact replica of the Convert Lead page using Visualforce and Apex. The result is an unmanaged package of Apex classes, custom Visualforce components, and a Visualforce page that you can use as a starting point for customizing the lead conversion process to the exact requirements of your business users.

The Convert Lead unmanaged package contains the following components:

Visualforce Page
  • leadConvertPage – The Visualforce page that replicates the standard Convert Lead page and uses the Standard Controller for the Lead sObject
Visualforce Components
  • leadConvertCoreComponent – Visualforce component containing the core UI elements for the Visualforce page
  • leadConvertTaskDescriptionComponent – Visualforce component containing UI elements related to the Task Description
  • leadConvertTaskInfoComponent – Visualforce component containing UI elements related to the common Task fields
  • leadConvertPageHeaderTextComponent – Visualforce component containing text that appears at the top of the Visualforce page
Apex Classes
  • ComponentControllerBase – Core Visualforce component controller
  • DateTimeUtility – Utility class containing Date / Time functions
  • leadConvertController – Visualforce controller extension
  • leadConvertCoreComponentController – Controller for the leadConvertCoreComponent Visualforce component
  • leadConvertTaskDescComponentController – Controller for the leadConvertTaskDescriptionComponent Visualforce component
  • leadConvertTaskInfoComponentController – Controller for the leadConvertTaskInfoComponent Visualforce component
  • PageControllerBase – Helper class to manage communications between the Visualforce page and components
  • TestLeadConvertPage – Unit tests for all Apex classes in the Convert Lead package

How do I use the custom Convert Lead page?

Implementing the custom Visualforce page is straightforward. You can choose to use either a standalone Custom Button (an example is included in the package) or overwrite the standard Convert button on the Lead object.

To use the Custom Button, simply drag it onto the desired Page Layouts from the Page Layout editor and optionally remove the standard Convert button from the page.

To override the standard Convert button, navigate to ‘Buttons, Links, and Actions’ in the Customize options for the Lead object. Click the ‘Edit’ link next to the Convert button, set the ‘Override With’ option to ‘Visualforce Page,’ and select the ‘leadConvertPage’ Visualforce page from the dropdown menu.

Where can I find the Convert Lead unmanaged package?

You can use the following link to the private AppExchange listing to download the app into your Unlimited Edition, Enterprise Edition, or Developer Edition org:

Custom Salesforce Lead Convert on AppExchange

Something to keep in mind – because this is an unmanaged package, updates to the package will not be applied to any Salesforce orgs in which the package is installed. We will be updating the package regularly based on feedback from the community, so when you see an update available you can download it, but you will need to manually apply any changes to your customized version of the application.

Force.com Data Modeling: The Advantages of Denormalization – Dreamforce ’13 Session Highlights

I recently had the opportunity to deliver my presentation Force.com Data Modeling: The Advantages of Denormalization to a sold out room at Dreamforce ’13. Based on the enthusiastic response and the feedback we received following the presentation about the lack of resources available on Salesforce Platform data modeling, I wanted to post highlights from the session here to give the community a starting point when thinking about designing a Salesforce data model. The session was inspired by a post entitled Force.com Data Modeling – Normalization is Not Your Friend that we published on this blog in 2010.

As of this writing, the video from the Dreamforce session has not yet been posted on YouTube, but as soon as it is we will embed it in this post.


Goals

What are our goals?

  1. We need to understand why data model design so important in the Salesforce world.
  2. We need to understand how the Force.com data model is much different than the relational databases that we grew up with.
  3. We have to “unlearn” what we have been taught about normalization patterns to apply what’s best for our Salesforce implementations.

Game Plan

Here’s the game plan.

We’re going to start at a high level and talk about the core differences between Force.com and traditional relational databases.

From there we’ll talk about how we need to balance requirements – which many times compete with each other – to design data models for Force.com. This is where the “normalization vs. denormalization” argument will play itself out.

We will cover design philosophies and best practices, and explore the pros and cons of these design patterns.

Database

What is normalization? Normalization is when you organize the tables and columns of a database to cut down on dependencies and data duplication. When we normalize, we try to break things down to a level where they exist only once in the database, and then we mash everything back together with junction tables and complex queries.

  1. You don’t want to have data appear in multiple places and be inconsistent (the “update” anomaly).
  2. You don’t want to create dependencies that prevent you from writing important data if you don’t have 100% complete data (the “insertion” anomaly).
  3. And, conversely, you don’t want to create dependencies that cause you to lose important data if you just want to delete a subset of the data (the “deletion” anomaly).

Denormalize for the cloud

In a highly transactional database where you have a large volume of write operations, normalization makes a lot of sense from the perspective that these write operations will be more efficient and perform better when stripped down to the bare minimum.

Now that we live in the cloud, and the way that we interact with data has changed, there is a growing movement to denormalize data models to improve performance and usability.

Why? If you think about how we interact in the cloud, we have human beings and machines (i.e. The Internet of Things) interacting with data sources across the Internet. Most of this interaction entails consuming data, not necessarily writing data.

From that perspective databases and APIs are being architected for read performance, and that means simplifying queries and flattening data structures as much as possible. How does a flatter data model improve performance? By reducing expensive joins.

This also creates a natural decoupling from rigid data modeling patterns, allowing people and apps to use the data in the most effective way for each specific application. This in turn also promotes scalability by allowing a theoretically unlimited number of consumers of the data, because dependencies between the data model layer of the architecture have been abstracted or removed completely.

So we have, at a high level, two competing philosophies. Now let’s throw Force.com into the mix.

Force.com

Force.com is a different animal completely. In the past, we owned the infrastructure and the databases. We could tune them to improve performance. We could make up for sloppy code in our applications by throwing more hardware at the problem or building indexes in our databases.

It was like we owned a house and we could tear down or build out whatever we wanted to in order to make things work.

Multitenant Architecture

Not with Force.com. We don’t own the house anymore. In the Force.com multitenant architecture, we rent an apartment.

We can do whatever we want to within the walls of this apartment, but we can’t just knock down a wall and add on. We have to work within our constraints to design the most effective solutions.

Under the Hood

Under the hood there are some important architectural items with Force.com that are important to understand when we’re designing data models.

The first is that you do not get direct access to the database. We are working with a metadata-driven database, where our data is represented as an abstraction of what is stored in the underlying relational database.

Object names, field names, types, etc. are all used to “describe” and provide context to the underlying data. If you haven’t done so already, I highly recommend reading “The Force.com Multitenant Architecture” white paper on DeveloperForce. It is a great resource that will help you understand the “Why” behind the Force.com architecture and why we need to look at it differently.

This concept of “describing” is important as we think through how to design and implement data models in Force.com.

If you think about CRM at its core, we are using Salesforce to describe our relationship with our customers. Every object that comes out of the box is used to describe something, whether it’s a company, a person, a selling cycle, a business process, or the relationships between all of these things.

SQL vs. SOQL

Another key difference between Force.com and the traditional databases that you’re accustomed to is the query language.

Do you know SQL? Do you know SOQL? Similar construct, but some big differences, right?

There are some great resources on DeveloperForce and in the Force.com community that break down SQL vs. SOQL, but the most important thing to keep in mind is that the ability to perform joins in SOQL is extremely limited.

In order to pull data from multiple objects in the same query, those objects must be explicitly related to each other.

If you start normalizing your data model in Force.com, you are going to run into serious issues with navigation, analytics, and security because normalization creates complexity. And because of SOQL and platform limitations, you’re going to have to write more and more code to piece together your data.

Because SOQL does not have the ability to join objects that are not related, if you want to perform joins you will have to perform multiple queries, cast the results to collections, most likely Maps, and write methods to iterate over the data sets and join the data manually.

Whereas if you denormalize and keep your data model as simple and flat as possible, you can keep your SOQL queries concise and avoid what amounts to writing numerous MapReduce functions in Apex.

What are some examples of Force.com denormalization? Address and phone fields are the most obvious examples. What about picklists and multivalue picklists? Do those require joins when retrieving vales? No, the values are stored as text in a record on an object.

This segues to my core philosophy for Force.com data modeling.

Entities

Entities describe something that should exist once and only once.

  • There is only one “you” in the world. “You” should only exist once in Salesforce.
  • In Force.com, entities are represented by objects and specific records within an object.

Attributes

Attributes provide individual “pieces” of context that together describe an entity as a whole.

  • “You” have a hair color. It is brown or blonde or red. Moscone West has a street address. It is 800 Howard Street.
  • In Force.com, attributes are represented by fields and types.

Relationships

Relationships provide context to describe how entities are connected, how they are ordered, and the conditions that make the relationship meaningful or unique.

  • “You” have relationships to other human beings. You have friends, coworkers, parents, grandparents, siblings, significant others. Your company has relationships with other companies. They can be suppliers, customers, partners.
  • In Force.com, relationships can be represented by both fields and objects. Relationship fields provide the direct 1:1 connection between entities, and additional fields provide the context to describe that connection. You can use junction objects to describe many to many relationships.

Balance

The key to designing effective data models is to find the balance between competing requirements and priorities.

  • Analytics. With Salesforce, you almost always have to begin with analytics in mind. How you design your data model impacts how you can organize data for reports and dashboards.
  • User Experience. Your design might be functional, but do people want to use it?
  • Clicks vs. Code. Sure, you can write code to make Force.com do just about anything short of parking your car for you, but can you meet requirements with out-of-the box functionality if you take the time to get the data model right? Think about the operations and maintenance implications before solving a problem with code.
  • Security. Are you creating an overly complex sharing model?
  • Performance. Are your response times lighting fast, or can you measure them with an hourglass? Performance also depends on the data volumes in your Salesforce org and how your company interacts with data.
  • Scalability. Will this data model grow with your business?

Force.com Data Modeling

Understanding how and when to represent entities, attributes, and relationships in Force.com is the most important concept you can master, as it underlies every decision you have to make when designing data models.

Beyond the constraints and limitations of Force.com, there really are no “hard and fast rules” to data modeling. What works for some might not work for others.

Here are some best practices that hold up in many situations.

Hierarchy

Embrace hierarchy.

  • We learned that SOQL needs objects to be explicitly related to each other in order for them to be included in the same query.
  • We know that we can traverse up to 5 levels upwards and 1 level downward in a relationship query.
  • Use formula fields to reference data from parent objects to provide additional context to child records without duplicating data.
  • Use rollup summary fields to provide context on parent records of Master-Detail relationships in lieu of creating triggers if it is an option.
  • Establishing Master-Detail relationships also enables cross-object workflows, allowing you to perform actions such as updating field values on parent records when workflow criteria is met on a child record.
  • Designing for hierarchy will enable deep analytics as you can create custom report types that give you three levels of parent-child-grandchild relationships, with the ability to traverse relationships at each level to bring in additional attributes.
  • There are performance implications if you go too crazy with relationship queries, especially in organization with large volumes of data, but for most organizations, designing with a hierarchy in mind will provide you with a solid foundation for your data model.

Know Your Siblings

Know your siblings.

  • Just because two objects are children of the same parent doesn’t mean that they have any knowledge of each other.
  • Avoid visibility issues between siblings by defining explicit relationships wherever possible.
  • Salesforce rolled out Joined Reports to counter this limitation in analytics, but if you are working in Apex, you will need to cast query results to Maps and perform iteration functions to match up data from the siblings.

Record Types

Learn to love the Record Type.

  • Rather than creating multiple objects for entities that are similar but require unique attributes, use Record Types to keep your data model flat and denormalized by segmenting entities into subtypes.
  • Record types allow you to display different page layouts based on User Profiles. You can also limit which Record Types are visible to specific Profiles.
  • Instead of creating different picklists for different entity subtypes, you can share common picklists but only include relevant values on a record type by record type basis.
  • Record types are indexed by default, giving you an ideal way to filter results and improve the performance of queries.

Avoid Clutter

Avoid clutter.

  • You get 500 custom fields per object in Enterprise Edition, and 800 in Unlimited Edition. Don’t be afraid to use them, and by all means flatten your data model as much as possible to simplify navigation and analytics, and to improve query performance.
  • But be smart about it, don’t let your data model become a mess.
  • Avoid clutter in your page layouts.
  • Remove deprecated fields as soon as possible.

Junction Objects

Learn to use Junction objects and a whole new world will open up to you.

  • Junction objects are similar in concept to junction tables in relational databases in that they allow you to establish M:M relationships between objects.
  • This is key – junction objects allow you to reference data and use it in multiple places without duplicating it. Because you are establishing relationships between objects, you have the ability to create related lists, giving you multi-dimensional views of relationships.
  • You’re probably already using junction objects today without even being aware of it. Contact roles on Accounts? You’re joining multiple contacts to accounts without duplicating any data – you don’t have to re-create contacts at multiple accounts just to establish a relationship between them. The contacts can exist once and only once in Salesforce. Granted, contact roles are limited in their functionality and may not be the best example, but it’s a common use case.
  • To create a junction object you simply need to create a new custom object that has two relationship fields on it.
  • A “pure” junction object will have two Master-Detail relationship fields, but I don’t always like to lock into Master-Detail relationships due to the restrictions on them. And sometimes creating Master-Detail relationships is not an option. One of the cool things about using two M-D fields with your junction object is that when you configure the related list on one of the joined parent objects, you can add any field from the other joined object as a column in the related list.
  • Beyond simply joining two records together, you can add attributes – custom fields – to a junction object to provide additional context around the relationship being established.
  • Again, creating additional objects may seem like we’re talking about normalization, but if you think about what we’re doing here, we are creating new entities that describe something unique – the relationship between two or more entities. Beyond the fact that junction objects are the only way to establish M:M relationships, embracing them can simultaneously allow you to simplify your data model while enabling new dimensions for navigation and analysis.

Avoid Duplication
Avoid data duplication.

  • Always reference with formula fields where possible and avoid copying data unless it is your only option.
  • If you cannot reference data because there is no explicit relationship, ask yourself if it’s feasible to create a relationship.
  • Can you avoid duplication if you were to use a junction object?
  • Avoid picklist sprawl – if you find yourself with two or more picklists that contain similar values, look into replacing them with a lookup to a related object. This somewhat flies in the face of the whole “denormalization” argument, but if you can design an object into your data model in a way that allows for referencing from multiple child objects and adding context to the relationship, you will save yourself the administrative overhead of having to update picklists on multiple objects whenever values change.

@DIChicago

Where do we go from here? What are our calls to action?

  • Take a look at your current data model. What can you do right now to make it better?
  • Experiment. Do you have your own Developer Edition org? If not, go to developerforce.com right now and sign yourself up. You can’t break anything, so get in there and play around.
  • Apply the principles that we introduced here if they make sense for your situation.
  • Read more about Force.com data modeling. There are so many resources on Developer Force, and there are a number of great blogs out there that can help you.
  • Get involved in the Salesforce community. Do you participate in the Salesforce Success Community? The Salesforce community is like nothing I’ve ever been involved with, there are great people out there doing great things, and we all want to help you succeed.

Create a Custom ‘New’ Button on a Related List to Return to the Parent Record After Clicking Save

Use Case

In Salesforce, when you click on the standard ‘New’ button on a Related List to create a new record on the child object from the record currently in context in a Detail Page, after you click ‘Save’ and save the new record, it returns you to the Detail Page for the newly created record by default. For parent-child object relationships that have high levels of data entry on the child object, this creates a user experience issue as the user will have to click on the link to the parent record in order to return to the Detail Page to continue adding child records or perform additional functions on the parent record.

Solution

The concept behind the solution is straightforward enough, but there are some tricky potential “gotchas” in the implementation that we need to be mindful of. What we are going to do is create a new Custom Button on the child / target object to replace the standard ‘New’ button that gets displayed on a Related List when looking at the Detail Page of a parent record.

The first thing that we need to do is grab the ID of the Lookup field on the child object that represents either the Lookup or Master-Detail Relationship to the parent object. This is important, because we will need to include two URL parameters that provide the record ID of the parent record, otherwise the lookup field will have a blank value when we create a new child record using this new custom button; this would require the user to manually perform a lookup, which is self-defeating since the expected behavior when clicking a ‘New’ button on a related list is to have the parent record ID available in context to pre-populate the dependent field.

To do this, simply go to the Detail Page for a record on the parent object. Navigate to the related list for the child object (obviously you would need to add this if it didn’t already exist), and click the ‘New’ button.  Copy the URL of the new page that appears and paste it somewhere that can be referenced throughout this process. It should look something like this:

https://naX.salesforce.com/a00/e? CF00NE0000002UJYd=Name+of+Parent+Record &CF00NE0000002UJYd_lkid=a03E0000002255P &retURL=%2Fa03E0000002255P

Whoa! What does all of this mean?

  • naX.salesforce.com – This is the instance of Salesforce that you are currently working on.  An example could be ‘NA9′.
  • a00 – This is the ID of the object that we are creating a new record for.
  • e? – This simply means that we are editing a record.  Now the ‘?’ character is the important part – this means that there are some parameters being passed through in the URL, and that whatever follows the ‘?’ is a parameter, which in this case is…
  • CF00NE0000002UJYd=Name+of+Parent+Record – This just happens to be the first parameter that was appended to this URL…do not worry about the order in which parameters appear in the URL. But when we see something with the prefix ‘CF’, it means that this is a reference to a Custom Field. The next 15 characters are the ID of the custom field. All URL parameters follow a ‘Key=Value’ convention, so after the Key (CF00NE0000002UJYd) and the ’=’ character, we get a value that represents the Name of the parent record…this is important, because it represents the human-readable value that gets pre-populated into your lookup field on the child record. NOTE: The 15-character ID that follows ‘CF’ will be a different value than what we are using here as an example; it is a unique identifier for every Custom Field in your Salesforce org.
  • &CF00NE0000002UJYd_lkid=a03E0000002255P – This is the next URL parameter. How do we know this? The ‘&’ character is our clue. Just as the ‘?’ character means that parameters are included in the URL, the ‘&’ character tells us that there is more than one parameter, and what follows the ‘&’ character is another URL parameter. In this case, the Key is ‘CF00NE0000002UJYd_lkid’. Does this look at all familiar? That’s right, it’s very similar to our previous URL parameter in that it starts out with the ‘CF’ convention for a Custom Field, and it has the same 15-character string representing the ID of the Custom Field, but you’ll notice that ‘_lkid’ is appended to the end. This stands for ‘Lookup ID’ and the corresponding value is a 15-character string representing the Record ID of the parent record. Why do we need this? Well, we may already have the Name of the parent record, but providing the ID of the parent record ensures that no additional data entry is required by the user in order for the value of the Lookup field to reference the correct parent record.
  • &retURL=%2Fa03E0000002255P – Again the ‘&’ character simply tells us that another URL parameter follows; in this case we get a Key of ‘retURL’ which tells Salesforce where to redirect the user in the event that the function is cancelled, with the Value being ‘%2F’ (the URL-encoded value for a ‘/’ character) plus the record ID of the record that was in context when the ‘New’ button on the Related List was clicked.

What do we do with all of this? Well, here’s the interesting part – that URL in and of itself is sufficient for getting a user to a screen where they can enter data for a new child record, and if they click the ‘Cancel’ button, Salesforce will know to return them to the Detail Page of the record that they were viewing when they clicked the standard ‘New’ button. But that doesn’t solve our problem – we’re not looking to return to the Detail Page when clicking ‘Cancel’ per se, we’re more interested in returning to the parent record’s Detail Page after the user clicks ‘Save’ on the new record. This URL doesn’t do the trick for us, so we need to somehow have Salesforce follow a different one when a new record is created from a Related List. But how?

The trick is to create a new Custom Button on the child object using these options:

  • Label – Whatever text you want displayed on this new button. Give it a descriptive name like ‘New (insert child object name here).”
  • Name – Give it a unique name, using only alphanumeric characters and underscores…no spaces or consecutive underscores.
  • Description – Whatever you’d like.
  • Display Type – Select “List Button” because we will be adding this to a Related List.
  • Behavior  – “Display in existing window without sidebar or header”
  • Content Source – “URL”

Now here comes the fun part. We need to construct a formula that will return a URL that provides us with all of the functionality of the standard ‘New’ button, but includes a URL parameter that tells Salesforce to return the user to the Detail Page of the parent record after this new record is saved.

This formula will be based on the URLFOR function, and at a high level will look like this:

{!URLFOR(target, id, [inputs], [no override])}

A specific example of the URLFOR function constructed to return a URL that provides us with everything we’re trying to accomplish here:

{!URLFOR( $Action.Child_Object_Name__c.New , null, [saveURL=Parent_Object_Name__c.Link, retURL=Parent_Object_Name__c.Link, CF00NE0000002aLV0_lkid=Parent_Object_Name__c.Id , CF00NE0000002aLV0=Parent_Object_Name__c.Name])}

  • target – This is where we want the user to end up when this hyperlink is clicked. In our case, we want to use $Action.Child_Object_Name__c.New, obviously changing ‘Child_Object_Name__c’ to the specific API name of your child object.
  • id – This is the ID of the record in context. This actually doesn’t pertain to us, because we’re creating a new record and will not have a record ID assigned until the record is saved. So in this case, let’s use ‘null‘ for the value of ‘id’.
  • inputs– Remember all of the URL parameters that we talked about above? Those go here using a Key = Value convention, with multiple items separated by commas. Don’t worry about not having the ‘?’ or ‘&’ characters in here, Salesforce will add them for you at runtime. So here are the URL parameters that we need:
    • saveURL=Parent_Object_Name__c.Link – Replace ‘Parent_Object_Name__c’ with the API name of your parent object. This parameter represents the secret sauce in everything we’re trying to accomplish – this is the URL that Salesforce will return the user to after the ‘Save’ button is clicked on the new record Edit Page.
    • retURL=Parent_Object_Name__c.Link – Replace ‘Parent_Object_Name__c’ with the API name of your parent object. This returns the user to a record Detail Page if the ‘Cancel’ button is pressed on the new record Edit Page.
    • CF00NE0000002aLV0_lkid=Parent_Object_Name__c.Id – Replace ‘Parent_Object_Name__c’ with the API name of your parent object, and replace the 15-character ID string contained in ‘CF00NE0000002aLV0_lkid’ with the ID of the Custom Field on the child object that looks up to the parent.
    • CF00NE0000002aLV0=Parent_Object_Name__c.Name – Replace ‘Parent_Object_Name__c’ with the API name of your parent object, and replace the 15-character ID string contained in ‘CF00NE0000002aLV0′ with the ID of the Custom Field on the child object that looks up to the parent.
  • no override – This is completely optional, and in fact we have left it out of our example. By default this is set to ‘false’, but if it were set to ‘true’ it would override any overrides that you may have in place for the ‘View’ for the record you are referencing in context.

Once you have this formula constructed, click on the ‘Check Syntax’ button. If there are errors, troubleshoot and correct them. If you get the “No syntax errors in merge fields or functions” all-clear, save this Custom Button and you’re almost done!

To get the Custom Button to appear on the Related List, edit the Page Layout(s) of the parent object.  Click on the little wrench that appears in the tab above the label of the Related List for the child object.  Expand the ‘Buttons’ section, uncheck the box next to the standard ‘New’ button, and under Custom Buttons, find your new button in the ‘Available Buttons’ section, click the ‘Add’ button (arrow facing right),  and your button should now appear under the ‘Selected Buttons’ section.  Click ‘OK’ and then save your Page Layout. Rinse and repeat for each Page Layout that needs to include this button in the Related List for the child object.

Test out your shiny new button by opening a record in the parent object, navigating down to the Related List for the child object, clicking on your custom ‘New’ button, and entering data into a new record for the child object…

  1. Does it take you back to the Detail Page for the correct record if you click ‘Cancel’?
  2. Is the correct record name populated in the Lookup field to the parent object?
  3. If you click ‘Save’ after entering data in the new record for the child object, does it take you back to the Detail Page of the parent record?
  4. Do you see the new record in the Related List for the child object?

Create a Custom Web Form Handler With Force.com Sites

No doubt you’ve run into this also…we needed a form handler that captured data for sObjects other than Cases or Leads (e.g. custom objects), we did not want to redirect visitors to a new page upon form submission, and our functional requirements were more complex than what the standard Salesforce form handlers could support. The standard Salesforce Web-to-Lead and Web-to-Case form handlers were not an option, so we had to create our own custom web form handler. And because we wanted to keep everything on Force.com, we decided to build this solution using VisualForce pages and an Apex controller served by Force.com Sites. We developed an alternative solution and wanted to share it with the community in the event it could help others.

Use case

You want to capture form data directly in Salesforce from either a VisualForce page served Force.com Sites or from an externally hosted page, but the standard Web-to-Lead or Web-to-Case web handlers do not meet your exact requirements. You may also be using custom JavaScript forms that post data using AJAX, and do not want to blindly pass data to a form handler that will not provide a return to indicate success or exceptions.

Ultimately, we wanted to expose our form handler so it could also be accessed by any of our forms on the web (Force.com Sites as well as others such as our WordPress blog, which uses an HTML / PHP-based form to collect data).

So, here’s what we did

To begin, you need to ensure that Force.com Sites is setup correctly if it is not already.  You can find information on creating and maintaining Force.com Sites here or here.  In our case, we created a “utility” Force.com Site so that we could keep the pages separate from our main Force.com Sites web pages.  We also concealed the Force.com Sites utility subdomain in our custom Site.URLRewriter implementation to avoid AJAX cross-domain issues, but that is a discussion for a future post.

You will need to code up a VisualForce Page and an Apex class to serve as a custom controller to capture the form data and cast values to specific fields in the target sObject.  The VisualForce page itself is very simple in its construct…essentially it will serve two purposes:

  1. Perform a specific Action that calls a PageReference method in the custom controller when the page is invoked.
  2. Return a value in a format that the process calling the form handler is expecting.  In our case, our AJAX method is expecting a JSON object with the result of the form submission (success or otherwise).

This is what the VisualForce page for the form handler that we use for www.deliveredinnovation.com looks like:

<apex:page  cache="false" controller="formHandlerSample" action="{!processForm}" showheader="false" contentType="application/jsonrequest">

	{success: {!success}}

</apex:page>
The elements of this page to take note of:
  1. The ‘controller’ attribute is the custom Apex class that contains the logic that will process the contents of the web form
  2. The ‘action’ attribute is the PageReference method contained in the Apex class that will process the form data and generate the required return string
  3. Because our AJAX script is looking for a JSON object to be returned, we declared the contentType of ”application/jsonrequest.” You may find that you need to return XML, HTML, or other text, so update this attribute to suit your specific requirements.

The form handler code:

public class formHandlerSample {

	public <String, String> urlParams;
	public String Error {get; set;}
	public Lead formLead = new Lead();

	public formHandlerSample() {
		urlParams = ApexPages.currentPage().getParameters();
	}

	public Boolean Success {
		get {

			if(Success == null) {
				Success = false;
			}

		return Success;
	}

	set;

	}

	public void processLead(Map<String, String> formFields) {

		if(formFields.size() > 0) {

			try {

				for(String fieldKey : formFields.keySet()) {

					if(fieldKey != null && fieldKey != 'null'){

						if(fieldKey == 'FirstName'){
							formLead.FirstName = formFields.get(fieldKey);
						}

						if(fieldKey == 'LastName'){
							formLead.LastName = formFields.get(fieldKey);
						}

						if(fieldKey == 'Title'){
							formLead.Title = formFields.get(fieldKey);
						}

						if(fieldKey == 'Company'){
							formLead.Company = formFields.get(fieldKey);
						}

						if(fieldKey == 'Phone'){
							formLead.Phone = formFields.get(fieldKey);
						}

						if(fieldKey == 'Email'){
							formLead.Email = formFields.get(fieldKey);
						}

						if(fieldKey == 'Description'){
							formLead.Description = formFields.get(fieldKey);
						}
					}
				}

				upsert formLead;
				Success = true;

			}

			catch(System.Exception e) {
				System.debug('Houston, you have a problem: ' + e);
				Success = false;
				Error = String.ValueOf(e);
			}

		}

		else {
			Success = false;
			Error = 'No form fields received';
		}

	}

	public PageReference processForm(){
		processLead(urlParams);
		return null;
	}

}

Render VisualForce Components Dynamically Based on Object Level Security

We recently came across an interesting situation that I’m sure many Force.com developers have faced at one point or another:  While using VisualForce with standard controllers in the context of a single object gives you access to a fair number of useful standard components exposed by the platform, when you venture beyond the single object or require functionality beyond what the platform gives you “out-of-the-box,” the custom code can pile up fast.

The specific use case that we had to address dealt with dynamically exposing components on the VisualForce page based on the object level security of the logged in user’s profile – in this case, it was buttons (apex:commandButton) and links (apex:commandLink). Because we were displaying input fields (apex:inputField) and output fields (apex:outputField) from a number of different custom objects, and because the actions corresponding to these buttons and links were custom PageReference methods that did a lot of data manipulation, we couldn’t simply reference standard actions such as {!save}.  And because not every user had access to the CRUD function associated with a given custom button or link, we wanted to only show them buttons and links that corresponded to an action that they could actually perform, rather than leading the user down a path that would ultimately throw an exception and frustrate them.

We knew we could write a fairly complex set of sObject describe methods that would populate boolean variables which we could then reference in the redered=”xxxx” attribute of the button and link definitions, but there had to be a better solution – we weren’t looking for a shortcut, but we didn’t want to leave the client with a ton of code that would be difficult to maintain and update over time. The solution ended up being elegant and straightforward, and leveraged a VisualForce global variable called $ObjectType that we didn’t realize was as powerful as it turned out to be.

The VisualForce documentation doesn’t do $ObjectType justice:

A global merge field type to use when referencing standard or custom objects such as accounts, cases, or opportunities as well as the value of a field on that object.

What salesforce.com should state in the documentation is that the $ObjectType is essentially a way to perform sObject describes natively in the context of the VisualForce page, without having to write a single line of custom controller or controller extension code.  It’s a pretty powerful function, and the only reason we went down the path of using it as a replacement for complex sObject describe methods is that we came across this page in the VisualForce Developer’s Guide, and thought to ourselves that if we could check object accessibility using $ObjectType.accessible, which looks a lot like the ‘isAccessible‘ sObject describe result method, then we might be able to use the similar nomenclature to check for object editability, deletability, etc.  This turned out to be the case, and we had our solution.

So let’s say you want to have a ‘New’ button on your VisualForce page that corresponded to a custom PageReference method called ‘newRecord’, and you only wanted that button to be visible to users that had ‘Create’ access on the corresponding standard or custom object.  What you want to do is something like this:

<apex:commandButton action="{!newRecord}" value="New" rendered="{!$ObjectType.myCustomObject__c.createable}" />

Using $ObjectType.objectName.createable returns a boolean (true/false) value that tells you whether the logged in user has the ability to create (the ‘C’ in CRUD) new records for the ‘myCustomObject__c’ custom object.  If the user does not have the necessary object level security, the expression will return ‘False’ and the component will not render.  If the user does have Create access, then the button will render because the expression will return ‘True.’

While we did not test this method with every possible sObject describe method, we did use it to create an ‘Action’ column to mimic the standard ‘Edit  |  Del’ pattern that you see on standard Salesforce list views, so we know for sure that you can check the ability to access, create, edit, and delete records for a given object.  The VisualForce code looks something like this:

<apex:pageBlockTable value="{!getSomeRecords}" var="r" cellpadding="8">

<apex:column width="10%" >

	<apex:facet name="header"><b>Action</b></apex:facet>

	<apex:commandLink action="{!myCustomEditLink}" rendered="{!$ObjectType.myCustomObject__c.updateable}">
		<apex:outputText value="Edit"/>
		<apex:param name="editId" value="{!r.id}"/>
	</apex:commandLink>

	<apex:outputText value=" | " rendered="{!$ObjectType.myCustomObject__c.updateable && $ObjectType.myCustomObject__c.deletable}"/>

	<apex:commandLink action="{!deploymentDelete}" onclick="return confirm('Are you sure?');" rendered="{!$ObjectType.Deployments__c.deletable}">
		<apex:outputText value="Del" />
		<apex:param name="deleteId" value="{!r.id}"/>
	</apex:commandLink>

</apex:column>

and so on…

As you can see, we were able to dynamically render the ‘Edit’ and ‘Del’ links, as well as the ‘ | ‘ spacing character all based on the CRUD / object level access of the user accessing the VisualForce page.  This saved us a lot of time, and will be fairly straightforward to maintain and update over time.

Here’s a little cheat sheet:

Show a component only if the user has ‘Create‘ access to an object:

<apex:commandButton action="{!newRecord}" value="New" rendered="{!$ObjectType.myCustomObject__c.createable}" />

Show a component only if the user has ‘Edit‘ access to an object:

<apex:commandButton action="{!editRecord}" value="Edit" rendered="{!$ObjectType.myCustomObject__c.updateable}" />

Show a component only if the user has ‘Delete‘ access to an object:

<apex:commandButton action="{!deleteRecord}" value="Delete" rendered="{!$ObjectType.myCustomObject__c.deletable}" />

 

Trigger to Automatically Submit Record for Approval

Use Case:

You want all new records for an object to be submitted to an Approval Process, but you do not want to rely on users to manually click the ‘Submit for Approval’ button after creating the record.

Solution:

After creating and testing a new Approval Process (Setup / App Setup / Create / Workflow & Approvals / Approval Processes), implement this simple Apex Trigger (the following example is for the Account object). You will also need to create a test method to ensure code coverage if your current production Apex Classes do not provide adequate coverage. Developers may also want to add try / catch statements to ensure that exceptions are caught and handled properly.

The Apex Trigger code:

trigger accountApprovalSubmit on Account (after insert) {

	for (Account a : trigger.new) {

		Approval.ProcessSubmitRequest app = new Approval.ProcessSubmitRequest();

		app.setObjectId(a.id);

		Approval.ProcessResult result = Approval.process(app);

	}

}

 

Create VisualForce Tab to Display Static List View for Standard or Custom Object

Use Case:

You would like to create a custom tab to display a specific list view for a standard or custom object rather than use the standard tab view that only displays recently viewed records.

Solution:

  1. From the standard or custom object tab, Edit an existing view or ‘Create New View.’
  2. Ensure that you give the view a Name, that you specify filter criteria, that you select the fields to display, and that you restrict visibility as necessary.
  3. When the view has been saved and you are returned to the tab, select the view from the dropdown.
  4. Copy the 15-character view ID in the URL and paste it to Notepad, or write it down.
  5. Create a new VisualForce page (Setup / App Setup / Develop / Pages) using the sample code provided below.
  6. Create a new VisualForce tab (Setup / App Setup / Create / Tabs) and select the VisualForce Page created in Step #5, provide a Tab Label, Tab Name, and Tab Style, and then apply the desired profile visibility for the new tab.
  7. Optional – hide the tab for the standard or custom object if your new tab is a replacement for the default tab.
  8. If you want to change the View that is displayed in the tab at any time, simply navigate back to the standard tab for the object and Edit the view to meet requirements.

The VisualForce Page code:

Note: Replace “xxxxxxxxxxxxxxx” with the 15-character ID of the View that you captured in Step #4 above.  You can adjust the ‘height’, ‘customizable’, and ‘rowsPerPage’ values as desired.

<apex:page>

	<apex:enhancedList listId="xxxxxxxxxxxxxxx" height="600" customizable="false" rowsPerPage="25"/>

</apex:page>

Force.com Tip: ‘New’ Button Override to Assign VisualForce Page to Specific Record Type Using Native Apex Code

You’ve probably come across this before…you need to create a custom VisualForce page for a specific Record Type, but overriding the ‘New’ or ‘Edit’ button seems to be an all-or-nothing proposition (i.e. you can do a single VisualForce page and embed the Page Layout using Apex:Detail, but you can’t mix custom pages with standard Page Layouts). We came across this recently at Delivered Innovation, and we want to share our solution with the community. This specific example involves the Salesforce Case object, but can be applied to any Standard or Custom Object.

Use Case: Client has multiple call centers supporting various product lines; support team ‘A’ requires a custom Wizard to rapidly search for and collect details for the Case record that the standard Salesforce search interface cannot provide.

Solution: While you can assign a specific Page Layout to a specific Record Type and embed VisualForce pages in the object Detail view, currently salesforce.com does not support embedded VisualForce Pages in the Edit view of a Page Layout; likewise, salesforce.com does not support custom VisualForce pages for specific Record Types.  The solution is to “intercept” the command to create a new record in an Object before Salesforce processes it, and this is accomplished with a 1-line VisualForce page and a StandardController extension that pulls and analyzes certain URL parameters to enhance the out-of-the-box process routing capabilities of Salesforce.

The VisualForce Page code:

<apex:page standardController="Case" extensions="caseRedirect" tabStyle="Case" showheader="true" action="{!redirect}" />

The Apex controller extension:

public with sharing class caseRedirect {

private ApexPages.StandardController controller;
public String retURL {get; set;}
public String saveNewURL {get; set;}
public String rType {get; set;}
public String cancelURL {get; set;}
public String ent {get; set;}
public String confirmationToken {get; set;}
public String accountID {get; set;}
public String contactID {get; set;}

public caseRedirect(ApexPages.StandardController controller) {

	this.controller = controller;

	retURL = ApexPages.currentPage().getParameters().get('retURL');
	rType = ApexPages.currentPage().getParameters().get('RecordType');
	cancelURL = ApexPages.currentPage().getParameters().get('cancelURL');
	ent = ApexPages.currentPage().getParameters().get('ent');
	confirmationToken = ApexPages.currentPage().getParameters().get('_CONFIRMATIONTOKEN');
	saveNewURL = ApexPages.currentPage().getParameters().get('save_new_url');
	accountID = ApexPages.currentPage().getParameters().get('def_account_id');
	contactID = ApexPages.currentPage().getParameters().get('def_contact_id');

}

public PageReference redirect() {

	PageReference returnURL;

	// Redirect if Record Type corresponds to custom VisualForce page

	IF(rType == 'xxxxxxxxxxxxxxx') {

		returnURL = new PageReference('/apex/insert_VF_Page_Here');

	}

	ELSE {

		returnURL = new PageReference('/500/e');

	}

	returnURL.getParameters().put('retURL', retURL);
	returnURL.getParameters().put('RecordType', rType);
	returnURL.getParameters().put('cancelURL', cancelURL);
	returnURL.getParameters().put('ent', ent);
	returnURL.getParameters().put('_CONFIRMATIONTOKEN', confirmationToken);
	returnURL.getParameters().put('save_new_url', saveNewURL);
	returnURL.getParameters().put('nooverride', '1');

	IF (accountID != null){

		returnURL.getParameters().put('def_account_id', accountID);

	}

	IF (contactID != null){

		returnURL.getParameters().put('def_contact_id', contactID);

	}

	returnURL.setRedirect(true);
	return returnURL;

}

}

Now for the important part – in order for this to work when Salesforce users create new Case records, you need to override the ‘New’ button for the ‘Case’ Standard Object.  This can be accomplished by selecting ‘Setup / Customize / Cases / Buttons and Links / ‘Override’ on ‘New’.  Select ‘VisualForce Page’ for “Content Type,” and then select the VisualForce page you created using your modification of the code above in the “Content Name” dropdown list, and you’re set.  The “Comment” area is optional. Don’t forget to set the security for this VisualForce page to provide the required Profiles with access.

Jeff Douglas has provided another method for achieving automated redirection to VisualForce pages on his blog.  You can find the link here.