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
Patrick DixonPatrick Dixon 

Struggling with wrapper class

I have custom objects that I'm rendering in a vf page using a custom controller. I'm making tentative steps towards a wrapper class as I've found that nothing else is going to work.

 

I'm trying to render all the 'content' objects that are details of 'content_item' objects, that are referenced in the 'page_layout object ... via a page_element object - which is a detail of page_layout and a child of content_item.  I've seperately proven the SOQL to give the required set of content records.

 

Here's my class and getter:

 

// Wrapper Class for contents
    public list<cWrapper> contents {get;set;}
    
    public class cWrapper {
        public list<Content__c> content {get;set;}
        // constructor method    
        public cWrapper(list<Content__c> c) {
            content = c;
        }
    }
// End Wrapper
    
    public list<cWrapper> getContents() {
        String pgId = ValidatePageName();
        contents = new list<cWrapper>();    // Initialise wrapper class variable

        for (Content_Item__c c: [select Id,
            (select Name, Content_Item__c, URL_Link__c, Image__c, Description_Text__c from Contents__r order by name)
            From Content_Item__c
            where Id in (Select Content_Item__c From Page_Element__c where Page_Layout__c = :pgId)
            order by Release_Date__c desc]) {
            // Add each set of contents records to the wrapper class variable
            contents.add(new cWrapper(c.contents__r));
            
        }
        return contents;
    }


But the problem is that I can't seem to access any of the results in the vf page.

 

<apex:repeat var="c" value="{!contents}" >

    {!c.content.Content_Item_c}

</apex:repeat>

 

gives

Save error: Unknown property 'VisualforceArrayList.Content_Item__c'

 

and

 

{!contents[0].content.Content_Item__c}

 

renders as a blank on the vf page.

 

Any suggestions as to what I'm doing wrong?

 

Best Answer chosen by Admin (Salesforce Developers) 
bob_buzzardbob_buzzard

Maybe I'm misunderstanding you, but I still don't think you need a wrapper class for this.  If you want the content item and its related content objects you should be able to simply return a list of content items to the page.

 

I've created a reduced version of your scenario and come up with the following:

 

Controller

 

 

public class ContentsController {

   public list<Content_Item__c> getContents() 
   {
        return [select Id, Name,
               (select Name, Content_Item__c, Description_Text__c from Contents__r order by name)
               From Content_Item__c
               order by Release_Date__c desc];
    }

 
}

 

 

Page:

 

 

<apex:page controller="ContentsController">
<apex:repeat value="{!contents}" var="item">
   ------<br/>
   <apex:outputField value="{!item.Name}"/><br/>
   ------<br/>
   <apex:repeat value="{!item.Contents__r}" var="content">
      Name: <apex:outputField value="{!content.Name}"/><br/>
      Description: <apex:outputField value="{!content.Description_Text__c}"/><br/><br/>
   </apex:repeat>
</apex:repeat>
</apex:page>

 

and the output that I get is:

 

 

------
Item 2
------
Name:Content 3
Description:Content 3

Name:Content 4
Description:Content 4

------
Item 1
------
Name:Content 1
Description:Lorem ipsum.

Name:Content 2
Description:Lorem Ipsum

 

 

Is this the sort of thing you are after, or is there more to it than that?

 

All Answers

Kevin SwiggumKevin Swiggum

it looks like cWrapper.content is not a content__c object...but a list of content__c objects...so in order to get to the contect__c.content_item__c property, you need to access it via the list (using another repeat loop or some other means)

 

 

Patrick DixonPatrick Dixon

Yes, but if I do:-

 

            <apex:repeat var="c" value="{!contents}" >
            <apex:repeat var="c1" value="{!c.content}" >
            test = {!c1.Description_Text__c}<br/>
            </apex:repeat>
            </apex:repeat>

 

I get nothing rendered - so the inner loop is never returning any data ... but there are 2 content_item records, 1 with 0 content detail records and the other with 4 content detail records, so there should be 4 lists returned from the wrapper, shouldn't there?

bob_buzzardbob_buzzard

I'm finding it difficult to see the benefit that the wrapper class would give you in this case.  It seems like you are wrapping a list of Content__c objects, which you could access directly.

 

That said, I can't see anything wrong with the logic - I've created a similar query in my dev org using accounts and contacts and can access the fields in the way that you are.

 

Have you confirmed through debug logging that the Content__c items that you expect are actually present in the list when accessed via the page?  

 

One thing to check - is your controller defined as "with sharing"?  If that is the case the the logged in user doesn't have access to the content_item__c or content__c records you may end up with less results than expected.

 

 

 

 

 

 

Patrick DixonPatrick Dixon

I couldn't get it to make any sense and having re-thought things, ended up with no wrapper class and this:

 

    public list<Content__c> getContents() {
        String pgId = ValidatePageName();
        list<Content__c> contents;

        for (Content_Item__c c: [select Id,
            (select Name, Content_Item__c, URL_Link__c, Image__c, Description_Text__c, Logo_Position__c from Contents__r order by name)
            From Content_Item__c
            where Id in (Select Content_Item__c From Page_Element__c where Page_Layout__c = :pgId)
            order by Release_Date__c desc]) {
            
            contents = c.contents__r;
            
        }
        return contents;
    }

 

... which seems to give me all the data - but just all lumped in together, rather than as seperate contents records for each of the content_items returned.  I'm then doing a check against the content_item id in the vf page, and rendering the matched content with it's respective content_item parent.

 

It all seems to work, but when I'm feeling brave I'll convert it all to a big wrapper class and run the vf page with 3 levels of apex:repeat loops.

 

Thanks for checking it over for me - it's good to know I'm on the right track.

bob_buzzardbob_buzzard

Maybe I'm misunderstanding you, but I still don't think you need a wrapper class for this.  If you want the content item and its related content objects you should be able to simply return a list of content items to the page.

 

I've created a reduced version of your scenario and come up with the following:

 

Controller

 

 

public class ContentsController {

   public list<Content_Item__c> getContents() 
   {
        return [select Id, Name,
               (select Name, Content_Item__c, Description_Text__c from Contents__r order by name)
               From Content_Item__c
               order by Release_Date__c desc];
    }

 
}

 

 

Page:

 

 

<apex:page controller="ContentsController">
<apex:repeat value="{!contents}" var="item">
   ------<br/>
   <apex:outputField value="{!item.Name}"/><br/>
   ------<br/>
   <apex:repeat value="{!item.Contents__r}" var="content">
      Name: <apex:outputField value="{!content.Name}"/><br/>
      Description: <apex:outputField value="{!content.Description_Text__c}"/><br/><br/>
   </apex:repeat>
</apex:repeat>
</apex:page>

 

and the output that I get is:

 

 

------
Item 2
------
Name:Content 3
Description:Content 3

Name:Content 4
Description:Content 4

------
Item 1
------
Name:Content 1
Description:Lorem ipsum.

Name:Content 2
Description:Lorem Ipsum

 

 

Is this the sort of thing you are after, or is there more to it than that?

 

This was selected as the best answer
Patrick DixonPatrick Dixon

Hi Bob

 

No - that's exacty what I'm after!

 

The problem that I had was that I was using

 

 

<apex:page controller="ContentsController">
<apex:repeat value="{!contents}" var="item">
------<br/>
<apex:outputField value="{!item.Name}"/><br/>
------<br/>
<apex:repeat value="{!contents.Contents__r}" var="content">
Name: <apex:outputField value="{!content.Name}"/><br/>
Description: <apex:outputField value="{!content.Description_Text__c}"/><br/><br/>
</apex:repeat>
</apex:repeat>
</apex:page>

 

Which is rejected on save with


Save error: Unknown property 'VisualforceArrayList.Contents__r'

 

and I couldn't seem to get around it.

 

I realise now that I needed the outer loop - many thanks for your help!