2

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>
  • 4
    Possible duplicate of querying related child object from parent in VF componenet – battery.cord Apr 28 '16 at 18:01
  • 1
    Hello - thanks for your previous answer. This question is slightly different that the previous one: Is there a way to get only the child relationship name of that particular API name which is mentioned in the VF page? Right now I am getting all the childrelationship name and there is no way to only get that child which I specified in in my VF page – SfdcBat Apr 28 '16 at 18:24
  • 2
    I mostly skimmed the question, saw mostly the same code, and assumed that it was a newer user who submitted the question again- after reading both your comment, and the post more closely, this does not appear to be the case. Absolutely my bad. – battery.cord Apr 28 '16 at 18:29
  • Can you provide a vf page which uses this component, or a snippet of how you would like to set up the page that contains this component? – battery.cord Apr 28 '16 at 18:31
  • No Worries,Sure, I will make the edit – SfdcBat Apr 28 '16 at 18:37
5

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.

  • 4
    +1 for dang that's a lot of work. And for nice, clean names. Although I would probably remove the Param smurf naming in your attributes. :) – Adrian Larson Apr 28 '16 at 22:01
  • I couldn't name them the same as the variables in the controller, and I wasn't sure what would be a better naming convention for them. If you think of something better, feel free to edit the post! – battery.cord Apr 28 '16 at 22:10
  • Ah yeah forgot about that unfortunate design pattern. You must think up two names! I wonder if there's an Idea about fixing it somewhere. – Adrian Larson Apr 28 '16 at 22:16
  • @battery.cord Appreciate your effort. I need to see how I can fit the logic in my code. Thanks – SfdcBat Apr 28 '16 at 23:38

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.