[SalesForce] Passing data from a parent visualforce page to a child visualforce page

I have successfully created a visualforce page (parent VF page) that injects another visualforce page (child VF page) into a jquery modal window.

The problem I am running into is passing some data from the parent VF page to the child VF page. The way I currently have it setup is using the apex:composition tag. However, I am not sure if that is the best approach. Here is the code…

Parent VF page

<apex:page controller="ChooseContactController">
JS/Stylesheets
<apex:form >
    <apex:pageBlock title="Choose a contact" mode="edit">
        <apex:pageBlockButtons >
            <input type="button" class="btn show-modal" value="New Contact"/>
            <apex:commandButton action="{!save}" value="Save" rerender="chooseContactPageMessagesWrapper"/>
        </apex:pageBlockButtons>
        <apex:outputPanel id="chooseContactPageMessagesWrapper">
            <apex:pageMessages />
        </apex:outputPanel>
        Data Display
    </apex:pageBlock>
    <apex:inputHidden value="{!primaryContactId}" id="primaryContactId" />
</apex:form>

<div id="modal-div" title="Create Contact" style="display:none;">
    <apex:composition template="CreateContact">
        <apex:define name="accountId">
            <apex:inputHidden value="{!accountId}" id="accountId" />
        </apex:define>
    </apex:composition>
</div>

In the apex:define tag, I am successfully passing the accountId to the child page…

Child VF page

<apex:page standardController="Contact" extensions="CreateContactExtensions">
<apex:form >
    <apex:pageBlock title="Create a new contact">
        <apex:outputPanel id="createContactPageMessagesWrapper">
            <apex:pageMessages />
        </apex:outputPanel>
        <apex:pageBlockButtons >
            <apex:commandButton action="{!save}" value="Save" rerender="createContactPageMessagesWrapper" />
        </apex:pageBlockButtons>
        <apex:pageBlockSection >
            <apex:inputField value="{!contact.firstName}"/><br />
            <apex:inputField value="{!contact.lastName}"/>
        </apex:pageBlockSection>
    </apex:pageBlock>
    <apex:insert name="accountId"/>
</apex:form>

When I inspect the html on the child VF page, the accountId is successfully being passed over. However, the CreateContactExtensions controller class does not recognize the accountId.

CreateContactExtensions controller

public class CreateContactExtensions 
{
    public String accountId { get; set; }
    public Contact contact { get; set; }
    ApexPages.StandardController standardController;

    public CreateContactExtensions(ApexPages.StandardController standardControllerParam) 
    {
        accountId = 'test';
        standardController = standardControllerParam;
        contact = (Contact)standardController.getRecord(); 
    }

    public String getAccountId()
    {
        return accountId;
    }

    public PageReference save() 
    {
        System.debug(accountId);
        contact.AccountId = accountId;
        standardController.save();
        return null;
    }
}

When I try to save the contact, the accountId is always set to 'test'. I am assuming that is because the child VF page extension controller class does not recognize accountId as a property.

Is there a way to get the extension controller class to recognize accountId as a property the way I have it setup? Should I be taking a different approach… maybe using apex:components? Is there a way to leverage a standard controller within a custom component?

Should I try one large custom visualforce page/controller? Although, I am not sure how viable this solution is because my child VF page is optional. To do this, I would have to move the child VF page markup into the form tag on the parent VF page. Then, when I post back to the parent VF custom controller, validation rules will run on all the properties. The contact property will need to have certain fields, i.e. last name, filled in for the validation rules to pass. Being that this piece is optional, sometimes those fields will not be filled in, the validation rules will fail, and I will never reach my method on the custom controller.

Am I simply missing something with my current architecture?

Best Answer

I would suggest the pattern of using a custom component that receives data from the parent page. As long as you are only needing the value within the component, it is a straightforward process. If, however, you are wanting to modify the value in the component and return that to the parent page, it gets more complicated.

In the simplest form (just passing the value to the component):

<apex:component controller="YourComponentControllerClass" selfClosing="true" allowDML="true">
    <apex:attribute name="accountId" description="" type="Id" assignTo="{!theAccountId}" />
    <!-- do your stuff here -->
</apex:component>


public with sharing class YourComponentControllerClass {
    public Id theAccountId {get; set;}

    public YourComponentControllerClass() {}
    // do your stuff here
}
Related Topic