+ Start a Discussion
mickpeamickpea 

Need Help - How to Create Custom Button that Returns to Original Object and Fills in Custom Field

Hello there!

 

This is my first post and I am incredibly new at creating VisualForce pages so please bear with me!

I have been searching the forums and reading up on a few different resources to accomplish my needs and I am comfortable creating the main content in my VisualForce page.

 

I created a custom button on my Case Detail page that navigates me to my VF page when a New Field Service needs to be created. All is working well (for the most part, still trying to figure out how to reliably fill in two look-up fields).

 

The problem I have is I want the "Save" button on the VF page to take me back to the original object and fill in a custom field on the Case Detail page with the service record created. I believe I have to do this with a Controller but I am getting confused as to how to implement this controller (as I am new to this). Also, is there a way to just link the VF custom button to the Case Detail page without a Controller?

 

The code for my VisualForce page is as follows:

 

<apex:page standardController="Field_Service__c">
  <apex:form >
    <apex:pageBlock title="New Field Service" mode="edit" id="thePageBlock">
      
      <apex:pageBlockButtons >
        <apex:commandButton action="retURL=/{!Field_Service__c.Case__c}+CF00NC0000005NROt={!Field_Service__c.Name}" value="Save"/>
        <apex:commandButton action="{!cancel}" value="Cancel"/>
      </apex:pageBlockButtons>
      
      <apex:pageBlockSection title="Information" columns="2">
        <apex:inputField value="{!Field_Service__c.Name}"/>
        <apex:inputField value="{!Field_Service__c.Store_Detail__c}"/>
        <apex:inputField value="{!Field_Service__c.Date_of_Service__c}"/>
        <apex:inputField value="{!Field_Service__c.Case__c}"/>
        <apex:inputField value="{!Field_Service__c.Field_Service_Name__c}"/>
        <apex:inputCheckbox value="{!Field_Service__c.Parts_Used__c}">
            <apex:actionSupport event="onchange"
                                rerender="thePageBlock"
                                status="status"/>
        </apex:inputCheckbox>
        <apex:inputField value="{!Field_Service__c.Field_Service_Description__c}" style="width: 98%; height: 40px"/>
        <apex:inputCheckbox value="{!Field_Service__c.Equipment_Rented__c}">
            <apex:actionSupport event="onchange"
                                rerender="thePageBlock"
                                status="status"/>
        </apex:inputCheckbox>
        <apex:pageBlockSectionItem ></apex:pageBlockSectionItem>
        <apex:actionStatus startText="Updating..." id="status"/>


      </apex:pageBlockSection>
      <apex:pageBlockSection title="Parts"  
      columns="2">
          <apex:inputField value="{!Field_Service__c.Service_Performed_By__c}">
              <apex:actionSupport event="onchange"
                                  rerender="thePageBlock"
                                  status="status"/>
          </apex:inputField>
          <apex:pageBlockSectionItem ></apex:pageBlockSectionItem>
          <apex:inputField value="{!Field_Service__c.Agilence_Technician__c}"
              rendered="{!Field_Service__c.Service_Performed_By__c='Agilence Customer Support' || Field_Service__c.Service_Performed_By__c='Both'}"/>
          <apex:inputField value="{!Field_Service__c.Contractor__c}"
              rendered="{!Field_Service__c.Service_Performed_By__c='External Contractor' || Field_Service__c.Service_Performed_By__c='Both'}"/>
      </apex:pageBlockSection>
      
      <apex:pageBlockSection title="Parts"  
      columns="1" 
      rendered="{!Field_Service__c.Parts_Used__c=true}">
       
        <apex:dataTable value="{!Field_Service__c}" var="part" 
        border="1" 
        cellspacing="4" 
        cellpadding="4" 
        align="center" 
        style="text-align: center; width: 80%"> 
             <apex:column headerValue="Quantity" style="width: 10%">
                  <apex:inputField value="{!Field_Service__c.Part_1_Quantity__c}" style="width: 99%"/>
                  <apex:inputField value="{!Field_Service__c.Part_2_Quantity__c}" style="width: 99%"/>
                  <apex:inputField value="{!Field_Service__c.Part_3_Quantity__c}" style="width: 99%"/>
                  <apex:inputField value="{!Field_Service__c.Part_4_Quantity__c}" style="width: 99%"/>
             </apex:column>
             <apex:column headerValue="Part Name" style="width: 20%">
                  <apex:inputField value="{!Field_Service__c.Part_1__c}" style="width: 99%"/>
                  <apex:inputField value="{!Field_Service__c.Part_2__c}" style="width: 99%"/>
                  <apex:inputField value="{!Field_Service__c.Part_3__c}" style="width: 99%"/>
                  <apex:inputField value="{!Field_Service__c.Part_4__c}" style="width: 99%"/>
             </apex:column>
              <apex:column headerValue="Model Number" style="width: 20%">
                  <apex:inputField value="{!Field_Service__c.Part_1_Model_Number__c}" style="width: 99%"/>
                  <apex:inputField value="{!Field_Service__c.Part_2_Model_Number__c}" style="width: 99%"/>
                  <apex:inputField value="{!Field_Service__c.Part_3_Model_Number__c}" style="width: 99%"/>
                  <apex:inputField value="{!Field_Service__c.Part_4_Model_Number__c}" style="width: 99%"/>
             </apex:column>
         <apex:column headerValue="Serial Number" style="width: 20%">
          <apex:inputField value="{!Field_Service__c.Part_1_Serial_Number__c}" style="width: 99%"/>
          <apex:inputField value="{!Field_Service__c.Part_2_Serial_Number__c}" style="width: 99%"/>
          <apex:inputField value="{!Field_Service__c.Part_3_Serial_Number__c}" style="width: 99%"/>
          <apex:inputField value="{!Field_Service__c.Part_4_Serial_Number__c}" style="width: 99%"/>
         </apex:column>
         <apex:column headerValue="Cost" style="width: 10%">
          <apex:inputField value="{!Field_Service__c.Part_1_Cost__c}" style="width: 99%"/>
          <apex:inputField value="{!Field_Service__c.Part_2_Cost__c}" style="width: 99%"/>
          <apex:inputField value="{!Field_Service__c.Part_3_Cost__c}" style="width: 99%"/>
          <apex:inputField value="{!Field_Service__c.Part_4_Cost__c}" style="width: 99%"/>
         </apex:column>
        </apex:dataTable>
      </apex:pageBlockSection>
      <apex:pageBlockSection title="Equipment"  
      columns="2" 
      rendered="{!Field_Service__c.Equipment_Rented__c=true}">
          <apex:inputField value="{!Field_Service__c.List_Equipment_Rented__c}" style="width: 99%"/>
          <apex:inputField value="{!Field_Service__c.Equipment_Rental_Cost__c}" style="width: 25%"/>
      </apex:pageBlockSection>
    </apex:pageBlock>
  </apex:form>
</apex:page>

 I know there are many improvements to be made to my code. I just want to nail down basic functionality first before I begin to refine it.

 

Any suggestions are greatly appreciated!

Best Answer chosen by Admin (Salesforce Developers) 
DaveHDaveH

It looks like in your testmethod you are using a var names "returnPage" but there is no declaration of it within the scope of that method.

 

static testmethod void testSaveAndReturnController(){

    Field_Service__c fieldService = new Field_Service__c();
    insert fieldService;
    ApexPages.StandardController controller = new ApexPages.standardController(fieldService);
  
    SaveAndReturnController testSARC = 
      new SaveAndReturnController(controller);
  
    // returnPage has not been declared but it is used here!
    system.assertEquals(testSARC.SaveAndReturn(), returnPage);
  }

 

All Answers

DaveHDaveH

The problem I have is I want the "Save" button on the VF page to take me back to the original object and fill in a custom field on the Case Detail page with the service record created.

 

Assuming that your are working with a customer controller (and not an extension) you will want to keep the objects you are working with as instace objects in your class. You can use apex:pageBlockButton to call a method in your controller which updates your instance object with the associated data and redirects the user to whatever page you want.

 

Remember in salesforce you can access an object by simply including the ID of the object right after the base URL. So if you want to redirect a user back to that object's detail page you can do the following:

 

// Instance variable declared above in our class
// Called memberObject

// Set some data in the controller
this.memberObject.someData = 'Blah';
update this.memberObject;

// redirect to /OBJECT_ID which will bring the user back to the detail page
PageRefrence pr = new PageReference('/' + this.memberObject.Id);
pr.setRedirect(true);
return pr;

 

mickpeamickpea

Thank you for the reply!

 

To my understanding, I am using a standard controller (for Field_Service__c). Would your suggestion still work or would I have to build a controller extension for this functionality?

DaveHDaveH

Yes, this will work for a standard controller as well.

mickpeamickpea

To be clear, will this method provide the functionality of updating the Parent Object with the number of the Service Record created rather than simply redirecting the user to the Parent Object.

 

So as an example:

 

User is on a Case page. (They must add in a New Field Service record)

     --> Click button which brings them to VF page for New Field Service. (They enter in the Service information)

     --> Click "Save" (They are redirected back to original case page; field on Case page is updated to reflect the Service Record created.)

 

Sorry if I am being confusing and asking many questions. Again, I am quite new at programming. I am asking twice though because I already am in the process of creating a trigger that identifies the Case.Id so I can pass a few parameters through (which admittedly I am struggling with as well), and I am thinking maybe it would be easier to place the function within that controller extension.

 

My controller extension code is below:

public class FieldServiceController{
  private String Store;
  private String Id;

  public FieldServiceController(ApexPages.StandardController controller){
      this.Id = ApexPages.currentPage().getParameters().get('Id');
  }
  public String getId() {
      return this.Id;}
  public void setId(String Id) {
      this.Id = Id;}
  
  public String getStore() {
      return this.Store;}
  public void setStore(String Store) {
      this.Store = Store;}
  
  //  public PageReference changePage() {          
  //      PageReference newpage = new PageReference('/apex/FieldService?'+Id+'&action=edit');
  //            return newpage;}
}

 Perhaps I could put it near the bottom?

 

 

DaveHDaveH

You're on the right track. The pseudo code should look something like this:

 

- User clicks on New Field Case button

- The VF page is called and the parent Case ID is passed in the URL

- In the constructor for the VF page grab the passed ID and save it in your instance var

- When the user saves the Field case, update the parent Case with the count of associated Field cases

- Redirect the user to the original parent Case detail page by using:

PageReference pr = new PageReference('/' + this.Id);

pr.setRedirect(true);

return pr;

mickpeamickpea

Thanks for all your help but I actually figured out a much easier solution to my troubles.

 

On the Parent object I created a roll up summary field to determine if a Child Record had been created (Field > 0). Depending on certain criteria, this was forced so the parent could not be closed without a child record attached. It may not be the best solution moving forward but it did accomplish what I wanted at the time.

 

I have a new issue where I am trying to add a SaveandReturn function to my visualforce page. So that when you click Save it brings you to the original page you started on prior to clicking New Child Record. I believe I have the functionality of this request. Now I am trying to create a test method for it. I feel I am very close.

 

public with sharing class SaveAndReturnController{

    // Field_Service__c fieldservice;
    private ApexPages.StandardController controller;
    public SaveAndReturnController(ApexPages.StandardController controller) {
    this.controller = controller;
    }

    public PageReference SaveAndReturn(){
        controller.save();
        PageReference returnPage = controller.cancel();
        returnPage.setRedirect(true);
        return returnPage;
    }
    
    static testmethod void testSaveAndReturnController(){

    Field_Service__c fieldService = new Field_Service__c();
    insert fieldService;
    ApexPages.StandardController controller = new ApexPages.standardController(fieldService);
  
    SaveAndReturnController testSARC = 
      new SaveAndReturnController(controller);
  
    system.assertEquals(testSARC.SaveAndReturn(), returnPage);
  }


}

 I am receiving an issue that "Variable does not exist: returnPage". How do I resolve this. Any help is appreciated. Or should I create a new thread?

DaveHDaveH

It looks like in your testmethod you are using a var names "returnPage" but there is no declaration of it within the scope of that method.

 

static testmethod void testSaveAndReturnController(){

    Field_Service__c fieldService = new Field_Service__c();
    insert fieldService;
    ApexPages.StandardController controller = new ApexPages.standardController(fieldService);
  
    SaveAndReturnController testSARC = 
      new SaveAndReturnController(controller);
  
    // returnPage has not been declared but it is used here!
    system.assertEquals(testSARC.SaveAndReturn(), returnPage);
  }

 

This was selected as the best answer
mickpeamickpea

Yeah, there were two issues and that was the first. I resolved this yesterday actually but I'll mark yours as correct seeing as it was the solution.

 

public with sharing class SaveAndReturnController{

    public SaveAndReturnController() {

    }


    private ApexPages.StandardController controller;
    public SaveAndReturnController(ApexPages.StandardController controller) {
    this.controller = controller;
    }

    public PageReference SaveAndReturn(){
        controller.save();
        PageReference returnPage = controller.cancel();
        returnPage.setRedirect(true);
        return returnPage;
    }
    
    static testMethod void testSaveAndReturnController(){

        Field_Service__c fieldService = new Field_Service__c();
        ApexPages.StandardController controller = new ApexPages.standardController(fieldService);  
        SaveAndReturnController testSARC = new SaveAndReturnController(controller);
  
    System.assertEquals(controller.cancel().getURL(), testSARC.SaveAndReturn().getURL());
  }
}

 The other issue: I was trying to insert a Field Service without proper parameters and it was catching my Validation Rule.