function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Robert RobinsonRobert Robinson 

Visualforce/Apex question: filtering a related list on a custom object

I have a custom object (Properties__c) that is a related list item for Accounts. Since some of the properties have been sold, users only want to see the Active Properties in the related list for Acccounts. I have attempted to use the Account Standard Controller in Visualforce along with an extension to accomplish this:
My Visualforce page markup is as follows:
<apex:page sidebar="false" showHeader="false" StandardController="Account" extensions="ActProp">
  <apex:pageBlock title="List of Properties">
 <apex:pageBlockTable value="{!props}" var="a">
        <apex:column value="{!a.Name}"/>
        <apex:column value="{!a.Asset_Type__c}"/>
        <apex:column value="{!a.RecordType.Name}"/>
        </apex:pageBlockTable>
    </apex:pageBlock>
 </apex:page> 


My Controller extension is as follows:
public class ActProp{
   public ActProp(ApexPages.StandardController cont) {}
   List<Property__c> props = [Select Name, RecordType.Name, Asset_Type__c from Property__c where Status__c ='1'];
      public List<Property__c> getprops(){
      return props;
      } 
}


My Visualforce page an custom controller both save with no issues; however, when I run the Page with a valid account (one with properties), the only thing that is returned is the "List of Properties" Block Title. I have read through the VF documentation and viewed related YouTube videos to try to figure this out. I know that I am thisclose, but am missing an element. Any assistance would be greatly appreciated. Thank you.
Best Answer chosen by Robert Robinson
RaidanRaidan
Ah, now I see. What you need is to create a StandardSetController on the Property object instead of the Account. See this document (https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/apex_pages_standardsetcontroller.htm) for more information. In this case you can filter the list by the account Id and status in the constructor (pass as a parameter - query string).

All Answers

RaidanRaidan
Hi Robert,

Perhaps if you use a property for the props, it will help. Something like this:
public class ActProp {
	public List<Property__c> props {get;set;}

	public ActProp(ApexPages.StandardController cont) {
		props = [SELECT Name, RecordType.Name, Asset_Type__c FROM Property__c WHERE Status__c = '1'];
	}
}

Don't forget to change the SOQL to also consider the Account Id later.
Robert RobinsonRobert Robinson
You don't have to use the "return props" part of the method?
I revised my code to match yours, but I am still getting a blank page.
RaidanRaidan
Can you run the SOQL first to make sure it returns at least one record? You can open the Developer Console and run the query in the Query Editor. 

 
Robert RobinsonRobert Robinson
Thank you. I was so focused on having a well-formed, valid statement that I did not pay attention to the Query! When I put the query into the Developer, it was blank as well. The problem was the value of "Status__c". Thankyouthankyouthankyou.
A question on your technique; does "{get;set} replace "getX()", "returnX" (shorthand?)
Robert RobinsonRobert Robinson
I also see that my query is missing the relation to the Account ID. It seems that I would pass this through the SELECT statement, but I am not sure how. Could you advise?
Robert RobinsonRobert Robinson
I tried to add to the Select statement:
props = [Select id, Name, RecordType.Name, Asset_Type__c from Property__c where id=:ApexPages.currentPage().getParameters().get(id) and Status__c = 'Active'];

but am seeing an Error: ActProp Compile Error: Variable does not exist: id at line 4 column 133

again I am missing the syntax, but am not sure where .
RaidanRaidan
Hi Robert,

Yes, using Property {get;set;} is a "shorthand" of the setter and getter methods. 

in your controller constructor, you can read the record id since you are using the Account standard controller.
public ActProp(ApexPages.StandardController cont) {
	String accountId = cont.getId();

	//use the accountId in the SOQL

}

 
Robert RobinsonRobert Robinson
I am still missing something in the query (or overthinking this). The new code is:

String accountId = cont.getId();
props = [Select Name, RecordType.Name, Asset_Type__c from Property__c where accountID=:ApexPages.currentPage().getParameters().get(id) and Status__c = 'Active'];

But I am seeing a "Variable does not exist: id at line 5 column 136". I think i am duplicating the "get(id)" method in the SOQL statement . Definitely falling down the rabbit hole.
RaidanRaidan
You will have to use the accountId variable instead of using the parameter get id. And are you sure the field name in Property__c is AccountId and not Account__c?
String accountId = cont.getId();
props = [Select Name, RecordType.Name, Asset_Type__c from Property__c where account__c=:accountId and Status__c = 'Active'];

 
Robert RobinsonRobert Robinson
Thank you for exceeding amounts of patience and assistance. I see where you are going with this; the Property object does not have an "account__c" field. I will determine the appropriate field and give this a try tomorrow after the gray matter between my ears has settled. Quite a bit to take in. Thanks again; will post the finished code to pay it forward.
RaidanRaidan
Please don't forget to mark one of my replies as the best answer :-) Thanks!
Robert RobinsonRobert Robinson
Absolutely. I would close this off tonight but my brain is deep fried. I'm  hoping a live example will help others. 
Robert RobinsonRobert Robinson
Ok. I couldn't wait. I am so close, so I took one last shot tonight.
I confirmed that the name of the linking field on the Property__c object is named Operator__c, so the key couplet is now:
String AccountID = cont.getId();
   props = [Select Name, RecordType.Name, Asset_Type__c from Property__c where Operator__c=:accountId and Status__c = 'Active'];


This is still returning no records, however, so I still have something out of order.
RaidanRaidan
When you open the page, did you open it from an Account (say, with a custom button)? If not, you will have to pass the id to the URL, something like /apex/ActProp?id=<pass_an_account_id_here>

And please make sure the query actually returns a record when you run it with Operator__c='<an_account_id>' AND Status__c = '1'
Jerun JoseJerun Jose
Hi Robert,

Lending my thoughts on this.

In your intial code:
ApexPages.currentPage().getParameters().get(id)
The id needs to be wrapped in quotes. The correct syntax would be:
ApexPages.currentPage().getParameters().get('id')
Since you are using a standard controller for your page, an alternate way to retrieve the account id value would be to use pre-defined methods available in the standard controller itself. Like the one provided by Raidan
String AccountID = cont.getId();
where cont is the variable name of the standard controller.

Needless to say, the query (and the page) would only work if you provide a valid account Id for the page to work with. Salesforce has some standard methods of passing the record id to a visualforce page. Some of these methods are:
1. When you embed a visualforce page in a page layout
2. When you call a visualforce page from a detail page button.
3. When you pass the record ID in the URL as a query string parameter. A sample format would be like ....force.com/apex/myVFPage?id=RecordIDGoesHere

As always, you can use the debug logs to inspect why your apex code is not working as desired. The debug logs will display the SOQL that was executed and the number of rows it returned. You can also use the system.debug() method to print custom messages on the log file. This can help to inspect the values passed to the SOQL (in this case the account ID).

Give it a try and let us know how it goes.
Robert RobinsonRobert Robinson
I confirmed that the Select statement below returns the two records that I expected to see:

Select Name, RecordType.Name, Asset_Type__c, from Property__c where Operator__c ='0015500000CQxfq' and Status__c = 'Active'

This gives me a good starting place tomorrow morning.
Robert RobinsonRobert Robinson
How bizarre. I copied the Class back from my Word Document, and it is working perfectly. To prove it, I activated a property under the same account, and it appeared in my "new", filtered Related List.

To summarize (for any others looking for sample code for a filter on a related field), the answer for my issue is as follows:
Visual Force Page
<apex:page sidebar="false" showHeader="false" StandardController="Account" extensions="ActProp">
  <apex:pageBlock title="List of Properties">
 <apex:pageBlockTable value="{!props}" var="a">
        <apex:column value="{!a.Name}"/>
        <apex:column value="{!a.Asset_Type__c}"/>
        <apex:column value="{!a.RecordType.Name}"/>
        </apex:pageBlockTable>
    </apex:pageBlock>
 </apex:page>


Apex Class
public class ActProp{
   public List<Property__C> props {get;set;}
   public ActProp(ApexPages.StandardController cont) {
   String AccountID = cont.getId();
   props = [Select Name, RecordType.Name, Asset_Type__c from Property__c where Operator__c=:accountId and Status__c = 'Active'];
      }
}

Now all that remains to complete the facsimile Related List page is to add the "New Properties" button and "Hover Help" that the current Related List has. But that can wait until morning!

Thank you again, Raidan, for a lot of instruction, but even more patience.
Robert RobinsonRobert Robinson
One last question: with the Apex Class listed above, would it be wiser to continue to build out the faux Related List (building on the Visualforce Page show above), or to override the standard Account Controller using the ActProp extension. I have a feeling that it is the latter, but wanted to confirm. Thanks.
RaidanRaidan
I don't really understand the question. Your class is already an extension of the Account standard controller. And since you want to build a list of Properties of an account, what you are doing looks correct to me. 
Robert RobinsonRobert Robinson
Sorry about that.
The purpose of this is to create a Visualforce page that is a filtered related list that can replace the standard related list with all of the functionality of the standard list. While the data output by the class is perfect (thank you again a million times for that!), it is missing those standard bells and whistles of the related list that is part of the account standard controller:
  • The "New Record" Button at the top of the related list section 
  • Hyperlinks which take the user to the specific record (with Open in New Window option)
  • The "Action" Column on the left with its Edit and Delete options
  • Hover help in the upper right hand corner of the related list box
  • The "Show More" items at the bottom of the related list box
Right now, my output is just the list.
My question is, which is the best route to provide these: continue building out the Visualforce page with these features, or was I going about this all wrong - should I have built out the class then used that class to override the values returned in the Standard Account Related List. It would be cool to work through delivering on these bullet point items, but if overriding the Related List values is the better option, that works as well.
RaidanRaidan
Ah, now I see. What you need is to create a StandardSetController on the Property object instead of the Account. See this document (https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/apex_pages_standardsetcontroller.htm) for more information. In this case you can filter the list by the account Id and status in the constructor (pass as a parameter - query string).
This was selected as the best answer
Robert RobinsonRobert Robinson
Thank you. I was so focused on the relationship between Account and Property that I overlooked the obvious.
Robert RobinsonRobert Robinson
Well, this is not so obvious...do you know of any samples of StandardSetController logic? I see snippets here and there, but nothing to sink my teeth into...
Robert RobinsonRobert Robinson
Scratch the last post. I have been able to cobble together a quick first pass (have not attacked the tied between Properties and Accounts; wanted a proof of concept first). The code:
VF
<apex:page controller="PropertyList2Con">
    <apex:pageBlock >
        <apex:pageBlockTable value="{!Property}" var="p">
            <apex:column value="{!p.name}"/>
            <apex:column value="{!p.Asset_Type__c}"/>
            <apex:column value="{!p.RecordType.Name}"/>
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page> 

Apex
public class PropertyList2Con {
List<Property__c> proplst=[select name, RecordType.Name, Asset_Type__c from Property__c];
ApexPages.StandardSetController ssc = new ApexPages.StandardSetController(proplst);
public List<Property__c> getProperty() {
return (List<Property__c>) ssc.getRecords();

}
}   


This returned a list in good form:

Property Name                                      Asset Type                                 Name                                                                                                 Property1                                        Assisted Living                            Seniors Housing
Property 2                                       Assisted Living                            Seniors Housing 
Property 3                                       Assisted Living                            Seniors Housing 

The problem is still the same as with the previous VF Page/Apex Class; it returns a flat list with none of the pieces (The "New Record" Button, Hyperlinks, Action Column) that the Standard Related List has. Is there additional markup that I have to do, or does the SSC have its own functionality that activates this? Thanks yet again.
Jerun JoseJerun Jose
Hi Robert, The controller changes will only affect the data returned to the page. To add the other features of the standard related list, you will need to make changes in your visualforce page. I'll try and reply again tomorrow with some more details, but I would start with looking into the attributes of the apex:relatedlist tag and looking into the child tags supported.
Robert RobinsonRobert Robinson
Thank you Jerun and Raidan for all assistance. This process has been drinking water from a firehose, but truly informative. I hope others are benefitting as well.
Robert RobinsonRobert Robinson
I spent the weekend reading the Apex documentation and researching this issue and  (filtered related list that has standard related list properties); and it appears that this is the bane of people's existence. I have not found the code that will replicate the related list's features (hyperlink, New Item Button, Action Columns); is there anything that provides a look at the code inside a Controller?
Robert RobinsonRobert Robinson
As unbelievable as this sounds, I have marked up the original VF page (Account StandardController with extension) to nearly completely mimic the Related List page the final element is the "Show 5 more" / "Go to list(x)" footer. Anyone have seen code for that?