[SalesForce] Get the specified child relationship Name from Parent

I have a Visualforce component where I am trying to get a related list (children) of any record (say Account, depends on the value I give in my VF page). I have two attributes in my VF component, objectName which gets the parent object and childRelationshipName which gets the child relationship name.

In my VF page the parent is Account and childRelationshipName is Contacts (any custom object child relationship name).

In RecordDisplayController, the controller for the VF component, I am trying to get the child relationship name specified in the childRelationshipName tag of the VF page. But in my code I was able to get all the child relationship names related to the parent.

Is there a way to get only the child relationship name of that particular API name which is mentioned in the VF page?

VF component:

<apex:component controller="RecordDisplayController">
    <apex:attribute name="objectName" description="An Sobject" type="Sobject" required="false" assignTo="{!objectvar}"/>   
    <apex:attribute name="childRelationshipName" description="Child Object" type="String" required="false" assignTo="{!childrelationship}"/>  
</apex:component>

RecordDisplayController:

public class RecordDisplayController {
    public sObject objectvar;
    public String childrelationship;
    public void setobjectvar(sObject s) {
        objectvar = s;
        DescribeSObjectResult describe = objectVar.getSObjectType().getDescribe();

        for (Schema.ChildRelationship child : describe.getChildRelationships()) {
            System.debug('===================> relationship name ' + child.getRelationshipName());
            System.debug('===================> field name ' + child.getField());
        }
    }

    public sObject getobjectvar() {
        return objectvar;
    }

    public void setchildrelationship(String s) {
        childrelationship = s;
    }

    public String getchildrelationship() {
        return childrelationship;
    }
}

VF page:

<apex:page standardController="Account">
    <c:recorddisplay childRelationshipName="Invoices" objectName="{!Account}" />
</apex:page>

Best Answer

So, you seem to be doing the right things, in the wrong locations. From what I can tell of the issues your having, you are trying to access the children in the component, instead of providing that data in the page which stores the components, as well as attempting to use a malformed query.

To help with this, I've created a small example, working off of how you have described the component in the comments. Hopefully you'll be able to adapt it into some code which will be useful to you.

This page is the page used to display the list, and holds an apex:repeat to loop over the child values, and create a number of related lists.

<apex:page standardController="Account" extensions="RecordListController">

    <apex:repeat value="{!childTypes}" var="child">
        <c:customrelatedlist typeOfParam="{!child['typeOf']}" relatedFieldParam="{!child['relatedField']}" relatedIdParam="{!Account['Id']}" />
        <hr />
    </apex:repeat>

</apex:page>

This class pulls the describe from the record in the standard controller (provided by the id param in the url), and creates a number of wrapper objects, which hold the needed information to create the related list components.

public class RecordListController {
    public List<ChildWrapper> childTypes { get; set; } 

    public RecordListController(ApexPages.StandardController c) {
        DescribeSObjectResult describe = c.getRecord().getSObjectType().getDescribe();

        childTypes = new List<ChildWrapper>();

        for (Schema.ChildRelationship child:describe.getChildRelationships()) {
            if (child.getChildSObject().getDescribe().fields.getMap().get('Name') != null) {
                childTypes.add(new ChildWrapper(child.getChildSObject().getDescribe().getName(), child.getField().getDescribe().getName()));
            }
        }
    }

    private class ChildWrapper {
        public String typeOf { get; set; }
        public String relatedField { get; set; }

        public ChildWrapper(String typeOf, String relatedField) { 
            this.typeOf = typeOf;
            this.relatedField = relatedField;
        }
    }  
}

Then, we have the related list component- it requires 3 parameters: the type, the related id field, and the related id (Which could be taken from the url, but is passed along here for clarity). This component displays the type, and then starts a loop, creating a number of links to the related records. You can display more detailed information here, but you'll need to think of a way to pass along field information, such as an extra parameter, or a custom setting. Additionally, if you know the type and the field with the related id, you can specify it here without needing to use any describe calls.

<apex:component controller="CustomRelatedListController" >
    <apex:attribute assignTo="{!typeOf}" name="typeOfParam" required="true" type="String" description="Type of Related Record" />
    <apex:attribute assignTo="{!relatedField}" name="relatedFieldParam" required="true" type="String" description="String of related field." />
    <apex:attribute assignTo="{!relatedId}" name="relatedIdParam" required="true" type="String" description="String of related Id." />

    <h2>
        {!typeOf}
    </h2>
    <apex:repeat var="o" value="{!objects}">
        <apex:outputLink value="/{!o['Id']}">{!o['Name']}</apex:outputLink>
        <br />
    </apex:repeat>
</apex:component>

Finally, the related list controller. All this controller does is store the needed data, and then provide the results of a query when requested.

public class CustomRelatedListController {
    public String typeOf { get; set; }
    public String relatedField { get; set; }
    public Id relatedId { get; set; }

    public List<sObject> objects;

    public CustomRelatedListController() {}

    public List<sObject> getObjects() {
        return Database.query('SELECT Id, Name FROM ' + typeOf + ' WHERE ' + relatedField + ' = \'' + relatedId + '\'');
    }
}

This example should work as is, if you move the files into your org and access the visualforce page with a valid id in the url.

Related Topic