[SalesForce] querying related child object from parent in VF componenet

I am trying to build a reusable VF component which can return all the child of an parent object. I just assign the parent object in my VF page and rest is taken care by the VF component to display the child records. So far I got the parent, but figuring out how to go from here to get the child records( or at least figure out how to query from the parent record that I have)

VF component:

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

<apex:pageBlock title="Related List">

<apex:pageblocktable value="{!relatedList}" var="r">
 <apex:column value="{!r.name}"/> 
</apex:pageblocktable>
</apex:pageBlock>                    
</apex:component>

Controller of VF component:

public class RecordDisplayController {

    public List<Contact> relatedList{get;set;}
    public sObject objectvar;

    public void setobjectvar(sObject s){
        objectvar=s;
        relatedList=[select Name from Contact where parentid=:objectvar.id]; // Does'nt work this way!!
    }

    public sObject getobjectvar(){
        return objectvar;
    }
}

My VF page just has:

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

The query to get the related list isn't correct. Also , is there a way I can get the child record of sObject objectvar; without mentioning the child name in the query explicitly? like – relatedList=[select Name from **Child_relationship_name** where parentid=:objectvar.id]; and relatedList can accomodate any Sobject like – public List<Sobject?> relatedList{get;set;}? Is there a way to achieve this?

Best Answer

You can try using the Schema.ChildRelationship object to get data about how the two objects are related.

public List<String> childRelationshipNames { get; set; }

public void getChildRecords() {
    DescribeSObjectResult describe = objectVar.getSObjectType().getDescribe();

    childRelationshipNames = new List<String>();

    for (Schema.ChildRelationship child:describe.getChildRelationships()) {
        childRelationshipNames.add(child.getRelationshipName());
    }

    String relationshipQuery = 'SELECT ';

    for (String relationship:childRelationshipNames) {
        if (relationship != 'null' && relationship != null) { 
             relationshipQuery += '(SELECT Id, Name FROM ' + relationship + '), ';
        }
    }

    relationshipQuery += 'Id, Name FROM ' + describe.getName() + ' WHERE ID = \'' + objectVar.Id + \'' LIMIT 1';

    objectVar = Database.query(relationshipQuery);
}

This will set all the child relationships on the given sObject stored in objectVar, by adding the name and id of all child objects to the object.

<apex:repeat value="{!childRelationshipNames}" var="relation">
    <apex:repeat value="{!objectVar[relation]}" var="child">
        <apex:outputLink value="{!child.id}">{!child.Name}</apex:outputLink>
    </apex:repeat>
</apex:repeat>

You can then take this data, and using the list of child relationship names, loop over those, and then the results inside of them.

Just to note- this can't be used on more than 20 child relationships, or you exceed the query limit, and not all children will have a name field- so some light filtering might be needed, depending on your org setup.

I haven't had a chance to run this on my org yet, but it should work as is. To get more detailed information would require using the getChildSObject() and getField() functions to get the proper field to filter by, and the correct object to query against.