3

I have been searching for a solution for this problem the whole day and I am getting nowhere.

Situation: I want to clone a custom object, update a few fields and insert the cloned object into the database. The object request__c is a child object.

My Approach:

  1. Create custom button on Request__c to call a Visualforce Page
  2. Create Visualforce Page (see below)
  3. Create ExtensionCreatorController (see below)

My Problem: I am stuck at getting the data from the Visualforce page to my cloned request. I am not sure which tags I have to use and how to then insert the new object. Help would be massively appreciated. Also just pointer to relevant links/documents would be helpful.

Visualforce Page:

<apex:page standardController="Request__c" extensions="ExtensionCreatorController">
    <apex:form>
        <apex:pageBlock title="My Request Input"> 
            <apex:pageBlockSection title="Input Section" columns="3">
                <apex:inputField value="{!Request__c.name}"/>
                <apex:inputField id="inpMovein" value="{!Request__c.Moveindate__c}"/>
                <apex:inputField id="inpMoveout" value="{!Request__c.Moveoutdate__c}"/>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form> 
</apex:page>`

ExtensionCreatorController:

public class ExtensionCreatorController {

private final Request__c requ;

public ExtensionCreatorController(ApexPages.StandardController stdController) {
    this.requ = (Request__c)stdController.getRecord();
}

public InsertClone () {
    cloneRequest = requ.clone();
    cloneReqeust.name = 'EX-'+requ.name;
    cloneRequest.Moveindate__c = */here Date to be specified in Visualforce Page/*;
    cloneRequest.Moveoutdate__c = */here Date to be specified in Visualforce Page/*;
    Insert cloneRequest
}}
  • 5
    By the way, thank you for posting a complete, well-specified, and well-formatted question. – David Reed Mar 20 '18 at 19:32
4

In this case, I don't think you have to perform a "clone" at all. You've currently wired your input fields on the Visualforce page directly to the standard controller's object, which is also the same object as requ based on your assignment in the constructor. requ is private and hence invisible to Visualforce, but the object it refers to is already exposed through the standard controller.

When you are ready to perform the clone operation in InsertClone, you can actually just clear the Id field from requ (which will have the data from the Visualforce page's input fields, since it's the same object as the standard controller's) and then perform an insert to create a new record. You don't need to call clone() or create the cloneRequest variable.

You do not need to assign the Moveindate__c and Moveoutdate__c fields, because that data entry is already handled by your Visualforce page's bindings.

You can simply assign the Name field as desired, and set the Id field to null before doing insert requ.

Edit: You do need to make sure that the object used by the standard controller contains all of the fields that you would like to be copied to the new object, including particularly any required fields. The standard controller automatically queries fields that it knows are required (those that are used in the Visualforce page by explicitly referencing them). For situations like this, where you want to have fields available in the object that aren't shown in the page, you need to inform the controller that it should query them for you.

There's a couple of ways to do this:

  1. You can include a reference to the field in the Visualforce page. (Probably not what you want to do here). This makes sure the standard controller populates the field without further intervention from you.
  2. Call addFields on the standard controller with a list of the API names of the fields you want to be populated. Basically, in your extension's constructor, you would do something like

    stdController.reset();
    stdController.addFields(new List<String>{ 'Opportunity__c', 'Landlord__c', ET_CETERA__C });
    this.requ = (Request__c)stdController.getRecord();

  3. Call addFields, but use the Describe API to obtain a list of all writeable fields rather than specifying them by hand.

Whether you choose (2) or (3) depends on exactly what you want to replicate from the original record and whether all of the fields are meaningful for the new object.

| improve this answer | |
  • David, thank you very much for your well structured reply! I just have one question regarding the insert, how would I go about triggering the insert action from my visualforce Page? – Fabian Bosler Mar 20 '18 at 20:03
  • 1
    Most likely, you'd want to use an <apex:commandButton> component, with its action method set to {! CloneRequest }. You can then have that method return a PageReference for the new object, to navigate the user there: return ApexPages.StandardController(requ).view(); – David Reed Mar 20 '18 at 20:08
  • David! Thank you very much. I implemented your suggestions and am getting a System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Opportunity, Landlord]: [Opportunity, Landlord] Error is in expression '{!InsertClone}' in component <apex:commandButton> in page mynewpagename: Class.ExtensionCreatorController.InsertClone: line 12, column 1 which I find surprising as I would expect requ to use the same data as the original object. – Fabian Bosler Mar 20 '18 at 20:11
  • David, thank you very much for the detailed and helpful explanation. Unfortunately I am not exactly sure how I would go about calling addFields on the standard Controller. I checked the documentation you attached but still don’t quite understand it. I would tremendously appreciate if you could elaborate on that a bit. – Fabian Bosler Mar 20 '18 at 21:30
  • 1
    I tried to elaborate a little - I hope that's helpful! – David Reed Mar 20 '18 at 21:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.