function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Charlotte GibsonCharlotte Gibson 

VF page not returning to SF1 layout on save - javascript issue?

Hi folks,

I've got a custom object (issue__c) hanging off Standard Case, which has a VF page on edit only. Save the issue, and (in the browser at least) the code returns you to the parent case record via a pageReference method returning PageReference('/' + cas.id).

However, I've encountered that fun little bug where in the SF1 app, the custom save button redirects the user not to the standard SF1 case page, but to the page as it looks in a browser.

After a lot of snooping, I've done my first bit of JavaScript, called by an onclick action on my VF button, which checks whether we're in SF1 or not, and if so, theoretically returns us to the SF1 case layout. I'm having difficulty getting it to redirect, however. Here's a cut-down version of my VF page:

<apex:page standardController="Issue__c" extensions="IssuesController" tabStyle="Issue__c">
 
  <script>
  
    function backToCase() {
    if ((typeof sforce != 'undefined') && (sforce != null) ) {
     // in SF1
     console.log("here we're in sf1");
     var backToCaseURL = 'javascript:sforce.one.navigateToSObject({!cas.id})';
    } else {
     // not in Salesforce1

     console.log("here we're in \'standard\' SF");
     console.log('case id is: {!cas.id}');
     window.location.href='/{!cas.id}';
    }
    return false;
   }

  </script>
 
  <apex:form >
  
   <apex:sectionHeader title="{!if(issueId==null,'Create Issue','Edit Issue')}" subtitle="Case {!issue.case__r.caseNumber} - Issue {!issue.name}">
    <apex:pageBlock title="Issue">
     <apex:pageBlockButtons >
      <apex:commandButton value="Save" action="{!save}" onclick="backToCase();"/>
     </apex:pageBlockButtons>
    </apex:pageBlock>
   </apex:sectionHeader>
 
  
  </apex:form>
</apex:page>

The "save" code on my controller is just this - very simple, and the code is saving fine. My gut tells me that the issue's not here, but thought I'd include it just in case:

public void save(){
  
   if(isNewIssue){
    insert issue;
    system.debug('Inserting Record');
   } else{
    update issue;
    system.debug('Updating Record');
   
   }
  
   
}
Thoughts? I'm quite new to Javascript.

Best Answer chosen by Charlotte Gibson
bob_buzzardbob_buzzard
There's a couple of issues here:

1. You've created a variable containing some JavaScript markup for SF1 navigation - backToCaseURL - but this won't do anything - you have to execute the JavaScript rather than assigning it.
2. The onclick handler will fire before the postback initiated by the save

The way I'd handle this is to change the commandbutton to rerender something, then define an actionstatus and execute the JavaScript via the onstop handler - this will fire after the action method executes.

Something like:

<apex:page standardController="Issue__c" extensions="IssuesController" tabStyle="Issue__c">
 
  <script>
  
    function backToCase() {
    if ((typeof sforce != 'undefined') && (sforce != null) ) {
     // in SF1
     console.log("here we're in sf1");
     // navigate to the page
     sforce.one.navigateToSObject('{!cas.id}');
    } else {
     // not in Salesforce1

     console.log("here we're in \'standard\' SF");
     console.log('case id is: {!cas.id}');
     window.location.href='/{!cas.id}';
    }
    return false;
   }

  </script>
 
  <apex:form >
  
   <apex:outputPanel id="panel" />
   <apex:actionStatus id="stat" onstop="backToCase" />
   <apex:sectionHeader title="{!if(issueId==null,'Create Issue','Edit Issue')}" subtitle="Case {!issue.case__r.caseNumber} - Issue {!issue.name}">
    <apex:pageBlock title="Issue">
     <apex:pageBlockButtons >
      <apex:commandButton value="Save" action="{!save}" rerender="panel" status="stat"/>
     </apex:pageBlockButtons>
    </apex:pageBlock>
   </apex:sectionHeader>
 
  
  </apex:form>
</apex:page>
Note that this doesn't have any error handling, so if there are any exceptions these will be ignored and the user taken to the case page regardless.

All Answers

bob_buzzardbob_buzzard
There's a couple of issues here:

1. You've created a variable containing some JavaScript markup for SF1 navigation - backToCaseURL - but this won't do anything - you have to execute the JavaScript rather than assigning it.
2. The onclick handler will fire before the postback initiated by the save

The way I'd handle this is to change the commandbutton to rerender something, then define an actionstatus and execute the JavaScript via the onstop handler - this will fire after the action method executes.

Something like:

<apex:page standardController="Issue__c" extensions="IssuesController" tabStyle="Issue__c">
 
  <script>
  
    function backToCase() {
    if ((typeof sforce != 'undefined') && (sforce != null) ) {
     // in SF1
     console.log("here we're in sf1");
     // navigate to the page
     sforce.one.navigateToSObject('{!cas.id}');
    } else {
     // not in Salesforce1

     console.log("here we're in \'standard\' SF");
     console.log('case id is: {!cas.id}');
     window.location.href='/{!cas.id}';
    }
    return false;
   }

  </script>
 
  <apex:form >
  
   <apex:outputPanel id="panel" />
   <apex:actionStatus id="stat" onstop="backToCase" />
   <apex:sectionHeader title="{!if(issueId==null,'Create Issue','Edit Issue')}" subtitle="Case {!issue.case__r.caseNumber} - Issue {!issue.name}">
    <apex:pageBlock title="Issue">
     <apex:pageBlockButtons >
      <apex:commandButton value="Save" action="{!save}" rerender="panel" status="stat"/>
     </apex:pageBlockButtons>
    </apex:pageBlock>
   </apex:sectionHeader>
 
  
  </apex:form>
</apex:page>
Note that this doesn't have any error handling, so if there are any exceptions these will be ignored and the user taken to the case page regardless.

This was selected as the best answer
bob_buzzardbob_buzzard
Edit - the actionstatus should be:

<apex:actionStatus id="stat" onstop="backToCase();" />


Charlotte GibsonCharlotte Gibson

Thanks Bob! You're absolutely right - I'd not even got as far as getting the code to run the SF1 side of things - it wouldn't even work in the browser! Thanks so much for pointers, will give em a shot today.

Cheers,

Charlotte

Charlotte GibsonCharlotte Gibson
Bob, that worked a treat - thanks so much! Off to write some error handling in my controller now. :)
rintyrinty
Hi Bob,

I have used the javascript function to save the value and it should return to objetc detail page.but mine code is not working please have a look into it.

 i have a opplineitem object realted to opprunity and in the add button i have used a vf page which is a custom action and it will open both in mobile and desktop.

please find the below code of mine:
in vf page:
function Redirect(){
       //alert('made it');
       //console.log(sforce);
        if((typeof sforce != 'undefined') && (sforce != null))
        {
            // Salesforce1  
            //alert("salesforce1");
            //console.log(sforce);
            var recordId ='{!theOpp.Id}';
            //alert('{!theOpp.Id}');
            Sfdc.canvas.publisher.publish({ name : "publisher.close", payload : { refresh:"true" }});
            sforce.one.navigateToSObject(recordId); 
            
               
         } 
         else {
            //Desktop
            alert('Desktop');
            alert('{!theOpp.Id}');
            window.location.href ='/{!theOpp.Id}';
           
        } 
        return false;
  
     }

Button logic:

 <apex:outputPanel id="panel1" />
 <apex:actionStatus id="stat" onstop="Redirect();" />
<apex:commandButton action="{!onSave}" value="Save" rerender="panel1" status="stat"/>

The value is saving properly in the backened in desktop as well as mobile..but the detail page is not refreshing with the updated value of related list in mobile app.

Please have a look into it and help is much appreciated!!!