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
Chad KovacChad Kovac 

Trying to simply show two sub-items (children) using Apex

Using the example here:
http://www.salesforce.com/us/developer/docs/pages/Content/pages_compref_dataTable.htm

I'm trying to get the following code to work:


Now, I this is only the first step.  I also have Opportunity_SubGroup__c that exist under Opportunity_Group__c
Apex page:
<apex:page controller="oppHierarchy" id="thePage">
	<apex:dataTable value="{!OGs}" var="Opportunity" id="theTable" rowClasses="odd,even" styleClass="tableClass">
		<apex:facet name="caption">table caption</apex:facet>
		<apex:facet name="header">table header</apex:facet>
		<apex:facet name="footer">table footer</apex:facet>
		<apex:column>
		        <apex:facet name="header">Name</apex:facet>
			<apex:facet name="footer">column footer</apex:facet>
			<apex:outputText value="{!OGs.name}"/>
		</apex:column>
		<apex:column>
			<apex:facet name="header">Quantity</apex:facet>
			<apex:facet name="footer">column footer</apex:facet>
			<apex:outputText value="{!OGs.Quantity__c}"/>
		</apex:column>
	</apex:dataTable>
</apex:page>
Class:
public class oppHierarchy {
	List<Opportunity_Group__c> OGs;
	public List<Opportunity_Group__c> getOGs() {
		if(OGs == null) OGs = [select name, Quantity__c from Opportunity_Group__c limit 10];
		return OGs;
	}
}


Ideally, I'll need to list related groups and subgroups on the opportunity page.

Maybe something like these will be needed in my Class?
public List<Task> getRelatedTasks() {
        return [select Id, Subject, ActivityDate, Status, Owner.Name, What.Name, Account.name, Type, CallType from Task where AccountId in :AllIds Order By ActivityDate Desc];
         
    
    }
    public List<Event> getRelatedEvents() {
        return [select Id, Legacy_Calltype__c, Subject, Type, Event_Status__c, Owner.Name, What.Name, ActivityDate from Event where WhatId in :AllIds Order By ActivityDate Desc];
    }

Instead of Tasks and Events I'd need Opportunity_Groups__c and Opportunity_Subgroups__c


Any help?


Best Answer chosen by Chad Kovac
Daniel B ProbertDaniel B Probert
ok so here we go i've had to complete change how i trying to do it and still think it might need a little bit of work to finish it off but take a look and test it and let me know what you think.

public class Extension_OppGroups {
    
    public List<Opportunity> oppsList { get; set; }
    public List<Opportunity_Group__c> ogList { get; set; }
    public List<Opportunity_SubGroup__c> osgList { get; set; }
    public Map<Id, List<Opportunity_SubGroup__c>> memIdInterestListMap { get; set; }
    Set<Id> ogIds = new Set<Id>();
    
    Map<Id, Opportunity_Group__c> ogMap = new Map<Id, Opportunity_Group__c>();
    public List<OppGroupWrapper> ogWrapperList { get; set; }

    public Extension_OppGroups(ApexPages.StandardController controller) { 
        STRING currentopp = ApexPages.CurrentPage().getparameters().get('id');
        ogList = [SELECT ID, Name, Quantity__c, Group_Total__c, Opportunity__c,Opportunity__r.Id FROM Opportunity_Group__c where opportunity__r.id =:currentopp ];
        memIdInterestListMap = new Map<Id, List<Opportunity_SubGroup__c>>();
        ogWrapperList = new List<OppGroupWrapper>();
        if(ogList.size() > 0) {
       
            for(Opportunity_Group__c mem : ogList) {
                ogIds.add(mem.Id);
                ogMap.put(mem.Id, mem);
            }
            osgList = [SELECT ID,Name, Unit_Price__c,Total_Price__c,Manufacturer__c,Opportunity_Group__c FROM Opportunity_SubGroup__c WHERE Opportunity_Group__c IN: ogIds];

        }
        if(osgList.size() > 0) {
            for(Opportunity_SubGroup__c intrst : osgList) {
                if(!memIdInterestListMap.containsKey(intrst.Opportunity_Group__c)){
                    memIdInterestListMap.put(intrst.Opportunity_Group__c, new List<Opportunity_SubGroup__c>());
                }
                memIdInterestListMap.get(intrst.Opportunity_Group__c).add(intrst);
            }
            for(Id osgId : memIdInterestListMap.keySet()) {
                ogWrapperList.add(new OppGroupWrapper(ogMap.get(osgId), memIdInterestListMap.get(osgId)));
            }
        }
    } 
    
    public class OppGroupWrapper {
        public Opportunity_Group__c oppgroup { get; set; }
        public List<Opportunity_SubGroup__c> oppsgList { get; set; }
        
        public OppGroupWrapper(Opportunity_Group__c oppgroup, List<Opportunity_SubGroup__c> oppsgList) {
            this.oppgroup = oppgroup;
            this.oppsgList = oppsgList;
        }
    }
}

vf page

<apex:page standardcontroller="opportunity" extensions="Extension_OppGroups" >
<apex:form >
<apex:pageBlock title="Opportunity Groups & Sub Groups" rendered="{!ogWrapperList.size!=0}">
    <apex:pageBlockTable value="{!ogWrapperList}" var="W" >
        <apex:column>
        <apex:facet name="header">Name</apex:facet>
        <apex:outputLink value="/{!W.oppgroup.ID}">{!W.oppgroup.Name}</apex:outputLink>
        </apex:column>
        <apex:column>
            <apex:facet name="header">Quantity</apex:facet>
            <apex:outputField value="{!W.oppgroup.Quantity__c}"/>
        </apex:column>
         <apex:column>
            <apex:facet name="header">Group Total</apex:facet>
            <apex:outputField value="{!W.oppgroup.Group_Total__c}"/>
        </apex:column>
        <apex:column>
            <apex:facet name="header">Opportunity Sub Groups</apex:facet>
            <apex:pageblockTable value="{!W.oppsgList}" var="I">
                <apex:column>
                    <apex:facet name="header">View</apex:facet>
                    <apex:outputLink value="/{!I.ID}">{!I.Name}</apex:outputLink>
                </apex:column>
                <apex:column>
                    <apex:facet name="header">Unit Price</apex:facet>
                    <apex:outputField value="{!I.Unit_Price__c}"/>
                </apex:column>
                <apex:column>
                    <apex:facet name="header">Manufacturer</apex:facet>
                    <apex:outputField value="{!I.Manufacturer__c}"/>
                </apex:column>
                <apex:column>
                    <apex:facet name="header">Total Price</apex:facet>
                    <apex:outputField value="{!I.Total_Price__c}"/>
                </apex:column>
            </apex:pageblockTable>
        </apex:column>
    </apex:pageBlockTable>
</apex:pageBlock>
</apex:form>
</apex:page>

i still think you should be thinking about overwritting the main opportunity page - that way when this is empty you're not going to be left with a blank box in the middle of the page...

let me know if you have any issues i haven't fully tested other than to create a could of opps with opp groups and subgroups..

cheers
dan

All Answers

Daniel B ProbertDaniel B Probert
hi chad do you want this to appear on the opportunity page or appear when you go to your apex/custompage?id=sfid

if so what's the relationships between Opportunity, Opportunity_Groups__c & Opportunity_Subgroups__c


Chad KovacChad Kovac
I'd like this to be a VF page that appears on the Opportunity page.
The Opporrtunity Group is linked to the Opportunity (Master) using "Opportunity__c"
The Opportunity Subgroup is linked to the Opportunity Group (Master) using "Opportunity_Group__c"

I think I'm on the right track but it's going to be a little more detailed than what I have.

Also, I can't just use a single Join between Opp Groups and Subgroups to return a single list because the list structures vary, right?
Daniel B ProbertDaniel B Probert
you are kind of - you need a where clause for the opportunity id

i would possibly overide the view page and use the standardcontroller="opportunity" then make this an extension.

i'll share an example in a bit just between locations..
Chad KovacChad Kovac
Thanks a ton Daniel. - I knew about the where clause etc., but I was literally trying to get it to pull ANYTHING for me lol so I left the limit 10 from the salesforce example.

We've been trying to find an Apex class close so I don't have to keep doing this painful trial and error self-teaching thing but it's been challenging.
Daniel B ProbertDaniel B Probert
i'll send you over an example vf extension that you should be able to work from in a bit - i.e. very little tweaking
Daniel B ProbertDaniel B Probert
hi chad hopefully this will be enough to get you going:

extension:

public with sharing class ext_opprelatedlist {

    public ext_opprelatedlist(ApexPages.StandardController controller) {

    }
    

    
    
    List<Opportunity_Group__c> oppgroup;
    public List<Opportunity_Group__c> getoppgroup() {
        if(oppgroup == null) {
            oppgroup = [SELECT id, Name,Quantity__c,Opportunity__c
                FROM Opportunity_Group__c 
                WHERE Opportunity__c =:ApexPages.CurrentPage().getparameters().get('id')];
            }
            return oppgroup;
        }
    List<Opportunity_Sub_Group__c> oppsubgroup;
    public List<Opportunity_Sub_Group__c> getoppsubgroup() {
        if(oppsubgroup == null) {
            oppsubgroup = [SELECT id, Name,Opportunity_Group__c,Opportunity_Group__r.Name,Opportunity_Group__r.Opportunity__c
                FROM Opportunity_Sub_Group__c 
                WHERE Opportunity_Group__r.Opportunity__c =:ApexPages.CurrentPage().getparameters().get('id')];
            }
            return oppsubgroup;
        }

}
vf page:

<apex:page standardController="Opportunity" extensions="ext_opprelatedlist">
    <apex:detail relatedList="false" />
    <apex:pageBlock title="Opportunity Group" rendered="{!oppgroup.size!=0}">
            <apex:pageBlockTable value="{!oppgroup}" var="oppg">
                <apex:column >
                    <apex:facet name="header">View</apex:facet>
                    <apex:outputLink value="/{!oppg.id}">View</apex:outputLink>
                </apex:column>
                <apex:column >
                    <apex:facet name="header">Number</apex:facet>
                    <apex:outputText value="{!oppg.Name}"/>
                </apex:column>
                <apex:column >
                    <apex:facet name="header">Quantity</apex:facet>
                    <apex:outputText value="{!oppg.Quantity__c}"/>
                </apex:column>
            </apex:pageBlockTable>
    </apex:pageBlock>
    <apex:pageBlock title="Opportunity Sub Group" rendered="{!oppsubgroup.size!=0}">
            <apex:pageBlockTable value="{!oppsubgroup}" var="oppsg">
                <apex:column >
                    <apex:facet name="header">View</apex:facet>
                    <apex:outputLink value="/{!oppsg.id}">View</apex:outputLink>
                </apex:column>
                <apex:column >
                    <apex:facet name="header">Name</apex:facet>
                    <apex:outputText value="{!oppsg.Name}"/>
                </apex:column>
                <apex:column >
                    <apex:facet name="header">Opportunity Group</apex:facet>
                    <apex:outputText value="{!oppsg.Opportunity_Group__r.Name}"/>
                </apex:column>
               
            </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>

this is setup for overriding the default view for an opportunity..

hope it helps steer you in  the right direction.



Chad KovacChad Kovac
I think this is really close... what I'm getting now is this:
User-added image
It seems to be repeating itself (the whole page) so I opened /apex/Opportunity_Hierarchy?id=006m0000002FZRP  and saw the same behavior.

If I can just get a working result for this I think I'd be able to conquer the world! At least.. of beginning APEX. ;)

I had to modify the code a bit because it's actually SubGroup not Sub Group:
Class:
public with sharing class ext_opprelatedlist {

    public ext_opprelatedlist(ApexPages.StandardController controller) {

    }
    
    List<Opportunity_Group__c> oppgroup;
    public List<Opportunity_Group__c> getoppgroup() {
        if(oppgroup == null) {
            oppgroup = [SELECT id, Name,Quantity__c,Opportunity__c
                FROM Opportunity_Group__c 
                WHERE Opportunity__c =:ApexPages.CurrentPage().getparameters().get('id')];
            }
            return oppgroup;
        }
    
    List<Opportunity_SubGroup__c> oppsubgroup;
    public List<Opportunity_SubGroup__c> getoppsubgroup() {
        if(oppsubgroup == null) {
            oppsubgroup = [SELECT id, Name,Opportunity_Group__c,Opportunity_Group__r.Name,Opportunity_Group__r.Opportunity__c
                FROM Opportunity_SubGroup__c 
                WHERE Opportunity_Group__r.Opportunity__c =:ApexPages.CurrentPage().getparameters().get('id')];
            }
            return oppsubgroup;
        }

}

Page:
<apex:page standardController="Opportunity" extensions="ext_opprelatedlist" showHeader="False" sidebar="False">
    <apex:detail relatedList="false" />
    <apex:pageBlock title="Opportunity Group" rendered="{!oppgroup.size!=0}">
            <apex:pageBlockTable value="{!oppgroup}" var="oppg">
                <apex:column >
                    <apex:facet name="header">View</apex:facet>
                    <apex:outputLink value="/{!oppg.id}">View</apex:outputLink>
                </apex:column>
                <apex:column >
                    <apex:facet name="header">Number</apex:facet>
                    <apex:outputText value="{!oppg.Name}"/>
                </apex:column>
                <apex:column >
                    <apex:facet name="header">Quantity</apex:facet>
                    <apex:outputText value="{!oppg.Quantity__c}"/>
                </apex:column>
            </apex:pageBlockTable>
    </apex:pageBlock>
    <apex:pageBlock title="Opportunity Sub Group" rendered="{!oppsubgroup.size!=0}">
            <apex:pageBlockTable value="{!oppsubgroup}" var="oppsg">
                <apex:column >
                    <apex:facet name="header">View</apex:facet>
                    <apex:outputLink value="/{!oppsg.id}">View</apex:outputLink>
                </apex:column>
                <apex:column >
                    <apex:facet name="header">Name</apex:facet>
                    <apex:outputText value="{!oppsg.Name}"/>
                </apex:column>
                <apex:column >
                    <apex:facet name="header">Opportunity Group</apex:facet>
                    <apex:outputText value="{!oppsg.Opportunity_Group__r.Name}"/>
                </apex:column>
               
            </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>



I'd like to include this as a VF page on the opportunity page but if I have to use it as a page all by itself, that's fine also.  Just so I can see how it was done so I can get in there and tweak it.

Chad KovacChad Kovac
User-added image
slightly easier to see the results here... wonder why SFDC makes it so small.
Daniel B ProbertDaniel B Probert
no idea why it's repeating like that very strange it's not doing it on mine.

if you want to embed it in a opp page then remove line 2 of the vf page.

then edit your opportunity page layout and you should see an option to add the layout - the reason included in a page override is that if there is nothing in there nothing is displayed thanks to the redended on the page:block..

User-added image
Chad KovacChad Kovac
That is awesome. I took out that second line referencing related lists and it's working perfectly.  Now I can add the proper information and look like a rock star thanks to you!  User-added image
Chad KovacChad Kovac
Hey Daniel, one last question.
If I want the Group to show only the Subgroups related to it, how could I do that?  Right now it shows a list of all Groups then a list of all Subgroups but the listed subgroups actually belong to the groups.
I suspect I need to modify this bit:
WHERE Opportunity_Group__r.Opportunity__c =:ApexPages.CurrentPage().getparameters().get('id')];


Daniel B ProbertDaniel B Probert
glad to have been of use..

have a great day - you still need to write the test class for this so you can deploy it into product

something like this should do the job:

@isTest
public class Test_extension{
    public static testMethod void myextensiontest(){
        
        //create the records needed for an opportunity / opportunity group and opportunity subgroup
       opportunity opp = new opportunity(name='demo',amount=10,stage='received',closedate=system.today();
       insert opp;
       opportunity_group__c oppgroup = new opportunity_group__c(name='demo',opportunity__c=opp.id);
       insert oppgroup;
opportunity_sub_group__c oppsubgroup1 = new opportunity_sub_group__c(name='demo',opportunity_group__c=oppgroup.id);
       insert oppsubgroup1;
opportunity_sub_group__c oppsubgroup2 = new opportunity_sub_group__c(name='demo',opportunity_group__c=oppgroup.id);
       insert oppsubgroup2;
      

        ApexPages.Standardcontroller sc1 = New ApexPages.StandardController(opp);
        ext_opprelatedlist  ext = new ext_opprelatedlist (sc1 );
        ext.getoppgroups();
        ext.getoppsubgroups();
        PageReference pageRef = Page.yourpagename; //update for your page name

        Test.setCurrentPageReference(pageRef);

    

    }

possibly typos in there but it'll give you a rough idea of what will be needed to deploy to production - aim for 100% and you should look to try and include some system.assertequals in there to validate your test at the end..
Daniel B ProbertDaniel B Probert
hmm on my one it's only showing the related groups and subgroups on the per record basis - i.e. 

i have 2 opportunities.

i created 3 groups on 1 opportunity and 1 on the other
i created 10 sub groups on each of the 4 groups.

on opp 1 i can see 3 groups and 30 subgroups.
on opp 2 i can see 1 group and 10 subgroups.

are you more meaning that you want it to show like this.

Group 1
Sub Groups
Group 2
Sub Groups
Group 3
Sub Groups

dan


Chad KovacChad Kovac
Yep, just like that Dan.   Kind of a nested hiearchy.  I can mess with the formatting on this end but getting the right records in the right places... 
Daniel B ProbertDaniel B Probert
hmm you'd have to one do one query in apex with a nester lookup inside of it - then use apex:repeat to display the nested records. if i get a chance later today i'll see if I can through some code together for you to do it.

but if you have a look at this link - it kind of gives a good example of how to do it.

http://salesforce.stackexchange.com/questions/13397/visualforce-displaying-from-nested-query
Chad KovacChad Kovac
I was thinking I could just do an inner join between Opp Groups and Subgroups?  I tried following what they did in that thread but I was lost as to where they were getting the value for the repeat: 
value="{!myFeedVar.FeedTrackedChanges}"

I don't see myFeedVar anywhere...
Daniel B ProbertDaniel B Probert
its in the apex:repear

<apex:repeat value="{!myFeed}" var="myFeedVar" >

so it's using myfeed in your apex class and assigned it own var in VF.


Chad KovacChad Kovac
I think I'm really close here...
<apex:page standardController="Opportunity" extensions="ext_opprelatedlist" showHeader="False" sidebar="True">
    <apex:pageBlock title="Opportunity Group" rendered="{!oppgroup.size!=0}">
            <apex:pageBlockTable value="{!oppgroup}" var="oppg">
                <apex:column style="text-align: center;vertical-align:top">
                    <apex:facet name="header" >View</apex:facet>
                    <apex:outputLink value="/{!oppg.id}" >{!oppg.Name}</apex:outputLink>
                </apex:column>
                <apex:column style="text-align: center;vertical-align:top">
                    <apex:facet name="header">Quantity</apex:facet>
                    <apex:outputText value="{!oppg.Quantity__c}"/>
                </apex:column>
                <apex:column style="text-align: center;vertical-align:top">
                    <apex:facet name="header">Total</apex:facet>
                    <apex:outputText value="{!oppg.Group_Total__c}"/>
                </apex:column>
                
                <apex:column >
                <apex:pageBlock title="Opportunity Sub Group" rendered="{!oppsubgroup.size!=0}">
                        <apex:pageBlockTable value="{!oppsubgroup}" var="oppsg">
                            <apex:column >
                                <apex:facet name="header">View</apex:facet>
                                <apex:outputLink value="/{!oppsg.id}">View</apex:outputLink>
                            </apex:column>
                            <apex:column >
                                <apex:facet name="header">Name</apex:facet>
                                <apex:outputText value="{!oppsg.Name}"/>
                            </apex:column>
                            <apex:column >
                                <apex:facet name="header">Opportunity Group</apex:facet>
                                <apex:outputText value="{!oppsg.Opportunity_Group__r.Name}"/>
                            </apex:column>
                        </apex:pageBlockTable>
                </apex:pageBlock>
                </apex:column>
            </apex:pageBlockTable>

    </apex:pageBlock>

</apex:page>

Class:
public with sharing class ext_opprelatedlist {

    public ext_opprelatedlist(ApexPages.StandardController controller) {

    }
    
    List<Opportunity_Group__c> oppgroup;
    public List<Opportunity_Group__c> getoppgroup() {
        if(oppgroup == null) {
            oppgroup = [SELECT id, Name,Opportunity__c,Quantity__c,Group_Total__c
                FROM Opportunity_Group__c 
                WHERE Opportunity__c =:ApexPages.CurrentPage().getparameters().get('id')];
            }
            return oppgroup;
        }
    
    List<Opportunity_SubGroup__c> oppsubgroup;
    public List<Opportunity_SubGroup__c> getoppsubgroup() {
        if(oppsubgroup == null) {
            oppsubgroup = [SELECT id, Name,Opportunity_Group__c,Opportunity_Group__r.Name,Opportunity_Group__r.Opportunity__c,Unit_Price__c,Total_Price__c,Manufacturer__c,Select_This_SubGroup_For_Opportunity__c
                FROM Opportunity_SubGroup__c 
                WHERE Opportunity_Group__r.Opportunity__c =:ApexPages.CurrentPage().getparameters().get('id')];
            }
            return oppsubgroup;
        }

}

I've been busting on this for about 8 hours now.  Not sure why this is so difficult a concept for me to grasp.  I have a lot of experience programming in various languages but something about this is twisting my brain!

In the image below you can see what's going on.  The items I crossed out in RED do not belong in those groups.  I only want to show the subgroups that are "under" the parent group in each section.   Ideally, I'd like a better way to format the output as well because I could have 4-6 columns in the GROUP and 4-6 in the subgroups.  I've tried closing the pageblock etc., and putting another in but when I do that it doesn't even show the subgroup anymore... 
User-added image

Daniel B ProbertDaniel B Probert
i know the feeling its taken me a while to get my head around it and even now i still miss understand a fair amount.

so the issue your having here is in your apex code.

if you check back on the example link you'll see it's one lookup - you need to update your first list to include a select within the subgroup.

i'm moving around today but have a go and i'll see if I can replicate and post an example a bit later..

cheers
dan


Chad KovacChad Kovac
Dan you're the best.  You might check out my post here as well:
https://developer.salesforce.com/forums/ForumsMain?id=906F0000000AX1mIAG
It is a request for a part-time contract resource to assist my company.
Daniel B ProbertDaniel B Probert
ok so here we go i've had to complete change how i trying to do it and still think it might need a little bit of work to finish it off but take a look and test it and let me know what you think.

public class Extension_OppGroups {
    
    public List<Opportunity> oppsList { get; set; }
    public List<Opportunity_Group__c> ogList { get; set; }
    public List<Opportunity_SubGroup__c> osgList { get; set; }
    public Map<Id, List<Opportunity_SubGroup__c>> memIdInterestListMap { get; set; }
    Set<Id> ogIds = new Set<Id>();
    
    Map<Id, Opportunity_Group__c> ogMap = new Map<Id, Opportunity_Group__c>();
    public List<OppGroupWrapper> ogWrapperList { get; set; }

    public Extension_OppGroups(ApexPages.StandardController controller) { 
        STRING currentopp = ApexPages.CurrentPage().getparameters().get('id');
        ogList = [SELECT ID, Name, Quantity__c, Group_Total__c, Opportunity__c,Opportunity__r.Id FROM Opportunity_Group__c where opportunity__r.id =:currentopp ];
        memIdInterestListMap = new Map<Id, List<Opportunity_SubGroup__c>>();
        ogWrapperList = new List<OppGroupWrapper>();
        if(ogList.size() > 0) {
       
            for(Opportunity_Group__c mem : ogList) {
                ogIds.add(mem.Id);
                ogMap.put(mem.Id, mem);
            }
            osgList = [SELECT ID,Name, Unit_Price__c,Total_Price__c,Manufacturer__c,Opportunity_Group__c FROM Opportunity_SubGroup__c WHERE Opportunity_Group__c IN: ogIds];

        }
        if(osgList.size() > 0) {
            for(Opportunity_SubGroup__c intrst : osgList) {
                if(!memIdInterestListMap.containsKey(intrst.Opportunity_Group__c)){
                    memIdInterestListMap.put(intrst.Opportunity_Group__c, new List<Opportunity_SubGroup__c>());
                }
                memIdInterestListMap.get(intrst.Opportunity_Group__c).add(intrst);
            }
            for(Id osgId : memIdInterestListMap.keySet()) {
                ogWrapperList.add(new OppGroupWrapper(ogMap.get(osgId), memIdInterestListMap.get(osgId)));
            }
        }
    } 
    
    public class OppGroupWrapper {
        public Opportunity_Group__c oppgroup { get; set; }
        public List<Opportunity_SubGroup__c> oppsgList { get; set; }
        
        public OppGroupWrapper(Opportunity_Group__c oppgroup, List<Opportunity_SubGroup__c> oppsgList) {
            this.oppgroup = oppgroup;
            this.oppsgList = oppsgList;
        }
    }
}

vf page

<apex:page standardcontroller="opportunity" extensions="Extension_OppGroups" >
<apex:form >
<apex:pageBlock title="Opportunity Groups & Sub Groups" rendered="{!ogWrapperList.size!=0}">
    <apex:pageBlockTable value="{!ogWrapperList}" var="W" >
        <apex:column>
        <apex:facet name="header">Name</apex:facet>
        <apex:outputLink value="/{!W.oppgroup.ID}">{!W.oppgroup.Name}</apex:outputLink>
        </apex:column>
        <apex:column>
            <apex:facet name="header">Quantity</apex:facet>
            <apex:outputField value="{!W.oppgroup.Quantity__c}"/>
        </apex:column>
         <apex:column>
            <apex:facet name="header">Group Total</apex:facet>
            <apex:outputField value="{!W.oppgroup.Group_Total__c}"/>
        </apex:column>
        <apex:column>
            <apex:facet name="header">Opportunity Sub Groups</apex:facet>
            <apex:pageblockTable value="{!W.oppsgList}" var="I">
                <apex:column>
                    <apex:facet name="header">View</apex:facet>
                    <apex:outputLink value="/{!I.ID}">{!I.Name}</apex:outputLink>
                </apex:column>
                <apex:column>
                    <apex:facet name="header">Unit Price</apex:facet>
                    <apex:outputField value="{!I.Unit_Price__c}"/>
                </apex:column>
                <apex:column>
                    <apex:facet name="header">Manufacturer</apex:facet>
                    <apex:outputField value="{!I.Manufacturer__c}"/>
                </apex:column>
                <apex:column>
                    <apex:facet name="header">Total Price</apex:facet>
                    <apex:outputField value="{!I.Total_Price__c}"/>
                </apex:column>
            </apex:pageblockTable>
        </apex:column>
    </apex:pageBlockTable>
</apex:pageBlock>
</apex:form>
</apex:page>

i still think you should be thinking about overwritting the main opportunity page - that way when this is empty you're not going to be left with a blank box in the middle of the page...

let me know if you have any issues i haven't fully tested other than to create a could of opps with opp groups and subgroups..

cheers
dan
This was selected as the best answer
Chad KovacChad Kovac
Yep, I agree.  Convert the Opportunity page to a VF page and conditionally display the box or not.  I have "VF Objects" embedded on pages because they're ugly and there's no way to dynamically size them.

I dropped the whols Facet, etc., thing.  I can't wrap my mind around all that vertical to horizontal conversion.  I simplified it quite a bit and am left with:
(Class)
public with sharing class opportunityControllerExtension {

    public opportunityControllerExtension(ApexPages.StandardController controller) {
    }
    
    List<Opportunity_Group__c> oppgroup;
    public List<Opportunity_Group__c> getoppgroup() {
        if(oppgroup == null) {
            oppgroup = [SELECT id, Name,Opportunity__c,Quantity__c,Group_Total__c, Tractor_Type__c,Trailer__c,
                (SELECT id, Name,Total_Price__c,Manufacturer__c,Year__c,Unit_Price__c,TermYears__c,MPY__c,Select_This_SubGroup_For_Opportunity__c
                    FROM Opportunity_SubGroups__r)
                FROM Opportunity_Group__c 
                WHERE Opportunity__c =:ApexPages.CurrentPage().getparameters().get('id')];
            }
            return oppgroup;
        }
}

and page:
<apex:page standardController="Opportunity" extensions="opportunityControllerExtension" showHeader="False" sidebar="True">
	<apex:repeat var="oppg" value="{!oppgroup}">
        <table border="0" width="100%">
	        <tr>
	            <th>Group</th><th>Quantity</th><th>Group Total</th><th>Type</th><th></th><th></th><th></th><th></th><th></th>
	        </tr>
	        <tr>
	            <td><apex:outputLink value="/{!oppg.id}" >{!oppg.Name}</apex:outputLink></td>            <td>{!oppg.Quantity__c}</td>            
	            <td><apex:outputText value="{0, number, $000,000}"><apex:param value="{!oppg.Group_Total__c}" /></apex:outputText></td>
	            <td>{!oppg.Tractor_Type__c}{!oppg.Trailer__c}</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
	        </tr>
	        <tr>
	            <th></th><th>Subgroup</th><th>Unit Price</th><th>Total Price</th><th>Model Year</th><th>OEM</th><th>TERM</th><th>MPY</th><th>Selected</th>
	        </tr>
	        <apex:repeat var="oppsg" value="{!oppg.Opportunity_SubGroups__r}">
		        <tr>
		            <td>&nbsp;</td>
		            <td>
		            <apex:outputLink target="_top" value="/{!oppsg.id}" >{!oppsg.Name}</apex:outputLink></td>
		            <td><apex:outputText value="{0, number, $000,000}"><apex:param value="{!oppsg.Unit_Price__c}" /></apex:outputText></td>
		            <td><apex:outputText value="{0, number, $000,000}"><apex:param value="{!oppsg.Total_Price__c}" /></apex:outputText></td>
		            <td>{!oppsg.Year__c}</td>
		            <td>{!oppsg.Manufacturer__c}</td>
		            <td>{!oppsg.TermYears__c}</td>
		            <td><apex:outputText value="{0, number, 000,000}"><apex:param value="{!oppsg.MPY__c}" /></apex:outputText></td>
		            <td>{!IF(oppsg.Select_This_SubGroup_For_Opportunity__c, "Yes", "No")}</td>
		        </tr>
	        </apex:repeat> 
    	</table>
    	<hr />
    </apex:repeat>
</apex:page>

I'm going to mess with the column formatting to force widths so I don't have two oddly sized tables.  Maybe I'll merge them into a single table.  Unknown.  I'm tired of messing with it! haha