Custom Buttons in SalesforceOne

Salesforce1 is Salesforce’s mobile app.  All kinds of data can be accessed and actions taken within Salesforce1, which is meant to be very configurable with just point-n-click actions.  But managing the flow in Salesforce1 in relation to custom buttons will need to be done differently than with page layouts in a standard web browser.

In a standard Salesforce page layout we are used to working with a Visualforce page in the following scenario…
1) I click on a custom button
2) The custom button takes me to a Visualforce page
3) The Visualforce page triggers some action to take place in the Apex class being used as the controller or extension.  Typically this is done using the ‘action’ attribute of the apex:detail tag.
4) When the work is done a PageReference is returned so that the flow can return to the detail layout of the object that has the custom button.

This all works very well, but it does not work exactly like that in Salesforce1.

You can use custom buttons in Salesforce1, but they must be detail buttons and be tied directly to a Visualforce page.  The Visualforce page must also be marked as being ‘Available for Salesforce mobile apps’, which can be found by going to ‘Develop’, ‘Pages’ and then clicking on your page.  These custom buttons will show up in the overflow menu by clicking on the down-arrow to the main action button on the page.  The Salesforce1 App Guidelines guide has a great picture of the overflow menu.  This means that the Visualforce page will have to rely on the StandardController functionality.  But in Salesforce1 if you return a PageReference like was done in #4 above you will be returned to the normal detail page based on the page layout instead of being returned to the Salesforce1 detail page. 

How do we get around this?

The first part in solving this is that we cannot rely on the Action attribute of apex:Page and we cannot rely on the PageReference being returned from a controller if we are in Salesforce1.  So we need our Visualforce Page to figure out if we are in Salesforce1 or not and then to take the correct action.  This blog post by Bob Buzzard shows how to run some Javascript during the onLoad event of the page properly.  This documentation from Salesforce shows us how to use the back() method to return to a Salesforce1 page.  Finally, this StackExchange page shows how to re-direct logic depending on if you are in Salesforce1 or not.

When we put it all together it can look like this:



<script type='text/javascript' src='/canvas/sdk/js/publisher.js'/>
    
<style>
    .requiredInput .requiredBlock, .requiredBlock {background-color: white;}
    .custompubblock div {display: inline-block;}
    .custompublabel {width:54px;}
</style>
    

<apex:actionFunction name="doInit" action="{!CallAction}"/>
<apex:actionFunction name="doInitSF1" action="{!CallActionSF1}"/>

<script>
function addLoadEvent(func){
  var oldonload = window.onload;
  if (typeof window.onload != 'function'){
     window.onload = func;
  }else{
     window.onload = function(){
        if(oldonload){
           oldonload();
        }
        func();
      }
   }
}
   
addLoadEvent(function(){
   if(typeof sforce !== "undefined" && sforce !== null) {
     doInitSF1();
     sforce.one.back(true);
    }else{
     doInit();
    }
}
);
</script>



What is happening on the page is that the addLoadEvent method will be called when the page loads and it will check if the sforce variable is available.  If it is, then a method will be called on the controller that should return a null PageReference.  That is very important so that you do not get to a standard detail page on the mobile app.  Then after the method is called the ‘sforce.one.back(true)’ method will be called which will re-direct back to the page from which the flow originated.

If there is not a ‘sforce’ object, then the page is not in Salesforce1, and the doInit() acionFunction can cause the ‘CallAction’ method to be called on the controller which will return the pageReference needed to get back to the original opportunity.

So in the end we have a Visualforce page that can be used both with a standard browser from a detail page and also with the Salesforce1 mobile app.  Page 195 of the Salesforce1 Developer’s Guide also describes this process well.

Cool!

Note that Custom Actions, which are different than custom buttons, can be tied to Visualforce Pages that use the standard controller also.  Note that these Custom Actions show up by clicking on the + button in the lower right-corner of the detail page.  The one issue I have seen with them is that these custom actions show the Visualforce page in the standard layouts, which does not look good.  If you have any ideas on working around this I would love to hear them since using Custom Actions seems to be the future preferred method when doing this type of work.

Thanks!  Good luck with your Salesforce1 projects.  Please let us know at Sundog Interactive if you need help with your mobile projects.

Comments

Returning visitor? Please login or register.

Leave A Comment