While it's not possible to add a Visualforce page or component to the standard Salesforce home page, it is possible to inject straight HTML and JavaScript into the home page via an HTML Area component. Furthermore, you can use Salesforce's AJAX Toolkit to connect to the API, which opens up a world of dynamic possibilities for your Home tab.
There's only one trick to connecting to the API: You need the current user's session ID. Luckily, this information is stored in the sid cookie and can be retrieved and easily stored in the sforce.connection.sessionId property.
From here, you can use all of the tools in the AJAX Toolkit to bring your data to life on the Home tab.
Insights and lessons learned from designing and implementing cloud solutions on the Salesforce1 Platform. Side adventures into Heroku with Ruby on Rails apps also included.
Friday, January 31, 2014
Monday, January 27, 2014
Extending Chatter Profile with Custom Subtabs
Out of the box, Salesforce only gives users limited access to user information through the Chatter Profile page. There are two tabs: Feed, showing the Chatter feed, and Overview, giving a nice overview of additional Chatter relationships and the ability to edit ~1 dozen User fields. However, organizations that want to extend the Chatter Profile page will not find any button-click admin options in Setup.
Thankfully, custom Profile subtabs give those orgs an option to extend the Chatter Profile without having to completely re-engineer the entire page (which is not really feasible considering the Chatter feed and related components). What's required is some Visualforce magic to expose related information directly on the Chatter Profile page as subsequent tabs coming after "Feed" and "Overview".
To provide access to personal data without exposing that data to other users, Salesforce provides a thoughtful separation of different subtab use cases. Admins have the option of showing custom subtabs in one or more of four different contexts.
- Profile (Others): When a user looks at someone else's profile in the internal Salesforce "community"
- Profile (Self): When a user looks at his/her own profile in the internal Salesforce "community"
- Profile in Communities (Others): When a user looks at someone else's profile in a customer or partner community
- Profile in Communities (Self): When a user looks at his/her own profile in a customer or partner community
Without restrictions on what to extend, subtabs really give developers the ability to deliver any functionality desired within the constraints of Visualforce. And knowing that the profile user's Salesforce ID can be retrieved from the sfdc.userId URL parameter, developers can provide a fully personalized experience for the user.
Labels:
Chatter,
Salesforce,
UI,
Visualforce
Thursday, January 23, 2014
Secret Search Layout Feature in Salesforce1
If you open an object tab in Salesforce1, you'll probably see something very similar to the screenshot below. A search box. Available list views. Recent items with... a teaser field on each item?
S1 has an interesting feature that enables users to see one field on each recent item on an object tab's home page. This feature appears to be undocumented in either the first version of the Salesforce1 App Developer Guide, or the "Customizing Search Layouts" Help page.
To configure which field appears here, modify the Columns Displayed for the Search Results Search Layout on the object. This is counter-intuitive, because in the browser app the columns displayed for recent items is controlled through the {!ObjectLabel} Tab Search Layout.
Have you found any other hidden configuration options for S1? Please share them in the comments!
P.S. Thank you to Brian Casey for tipping me off to this interesting discovery!
Labels:
mobile,
object,
S1,
Salesforce,
UI
Friday, December 20, 2013
Testing Apex @future Methods in Salesforce
To write functional Apex unit tests for methods having the future annotation, all you need to do is use Test.startTest() and Test.stopTest(). The general structure of your testMethod will look like the following.
Whether it's scheduled Apex or @future Apex, calling Test.stopTest() will cause those methods to run in sequence in your test method. Test.stopTest() then allows you to validate the results of @future Apex using normal means.
Whether it's scheduled Apex or @future Apex, calling Test.stopTest() will cause those methods to run in sequence in your test method. Test.stopTest() then allows you to validate the results of @future Apex using normal means.
Labels:
Apex,
code,
Force.com,
Salesforce,
unit test
Wednesday, December 4, 2013
Mark Read Checkbox in Field Permissions for Salesforce Profile with Bookmarklet
Below is a functional bookmarklet that you can use to mark the Read checkbox for every single field in the Field Permissions section of an object's settings within a Salesforce Profile.
To use the bookmarklet:
- Drag the link ("bookmarklet") on to your browser's bookmarks bar
- Open an object settings page within a Salesforce Profile
- Click the bookmarklet in your browser's bookmarks bar
Note: This was tested with Chrome on Windows 8 in Salesforce Winter '14.
Labels:
hack,
JavaScript,
Salesforce
Tuesday, December 3, 2013
Deploying Destructive Changes Using Workbench
Sometimes, especially in the case of custom Apex or Visualforce, a Salesforce admin or developer needs to delete components from an org. However, Salesforce's user-friendly change sets feature does not allow admins to propagate component deletions. The only semi-automated alternative to performing these deletions, especially in production orgs, is to leverage the metadata API.
Fortunately, with the availability of Workbench on Developer Force, the steps required for deploying destructive changes (that delete components) are pretty simple:
Fortunately, with the availability of Workbench on Developer Force, the steps required for deploying destructive changes (that delete components) are pretty simple:
- Create a package.xml file
- Create a destructiveChanges.xml file
- Bundle the two files together in a .zip file
- Deploy the .zip package using Workbench
As you can see from this sample .zip package, the files are fairly simple and straightforward. Multiple types of metadata can be removed with a single package.
The exact steps for deploying using Workbench 29.0.1 are:
- Open the migration menu, then click Deploy
- Click Browse... and select the .zip package file
- Mark the "Rollback On Error" checkbox
- Mark the "Single Package" checkbox
- Mark the "Run All Tests" checkbox
- Click Next
- Review the deployment options, then click Deploy
The results, successful or otherwise, will be displayed in Workbench for you to review once the deployment process is complete.
Labels:
Apex,
API,
Force.com,
metadata,
Salesforce,
Visualforce
Friday, October 4, 2013
Contact Age (Years) Formula Field In Salesforce
Due to complications in the human calendar, with leap years and different numbers of days in different months, it's not always easy to calculate the exact human age of a person for CRM purposes. In Salesforce, a more reliable method of calculating the age is through a formula field with the following formula:
The components of this seemingly complex formula are broken down below.
This gives us the expected age. If a Johnny was born in 2000, and it's now 2013, we would expect the (max) age of Johnny to be 13 once his birthday arrives in 2013.
By assuming that there is a max of 31 days in any given month, treating the month-day relationship as two "digits" in a base-31 number allows us to do a simple arithmetic comparison to see whether the birthday has come and gone in the current year. This works even for the rare February 29 birthdays.
So, if the birthday has passed, then the expected age is fine and we don't need to make any adjustments. If the birthday has not passed, then we subtract one from the max expected age to arrive at the correct current age.
( YEAR( TODAY() ) - YEAR( Birthdate ) )
+ IF(
MONTH( TODAY() ) * 31 + DAY( TODAY() ) >=
MONTH( Birthdate ) * 31 + DAY( Birthdate ) ,
0 , -1 )
The components of this seemingly complex formula are broken down below.
YEAR( TODAY() ) - YEAR( Birthdate )
This gives us the expected age. If a Johnny was born in 2000, and it's now 2013, we would expect the (max) age of Johnny to be 13 once his birthday arrives in 2013.
IF( ... , 0 , -1 )
By assuming that there is a max of 31 days in any given month, treating the month-day relationship as two "digits" in a base-31 number allows us to do a simple arithmetic comparison to see whether the birthday has come and gone in the current year. This works even for the rare February 29 birthdays.
So, if the birthday has passed, then the expected age is fine and we don't need to make any adjustments. If the birthday has not passed, then we subtract one from the max expected age to arrive at the correct current age.
Labels:
formula,
Salesforce
Subscribe to:
Posts (Atom)


