[SalesForce] Custom component does not display values from assignTo attribute

VF page:

<apex:page standardcontroller="opportunity" >
<c:vendortab componentValue="{!Opportunity.AccountId}"/>
</apex:page>

VF Component:

<apex:component controller="componenttester" access="global">
<apex:attribute name="componentValue" description="testing" type="Id" required="required" assignTo="{!acct}"/>
<apex:form >
<apex:tabPanel id="theTabPanel" >
<apex:tab label="Contactdetails" name="Contactdetails" id="Contactdetails">
<apex:pageBlock title="Account Detail">
<apex:pageBlockSection title="Contacts" columns="1">
<apex:pageBlockTable value="{!conts}" var="cont" rows="10">
<apex:column value="{!cont.Id}"/>
<apex:column value="{!cont.Name}"/>
<apex:column value="{!cont.Email}"/>
<apex:column value="{!cont.Phone}"/>
</apex:pageBlockTable>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:tab>
</apex:tabPanel>
</apex:form>
</apex:component>

apex class:

public class componenttester 
{
public List<Contact> conts {get; set;}
public Id acct {get; set;}
public componenttester(){
}
public void componenttest() 
{
system.debug(acct);
conts=[select id, Name, Email, Phone from Contact where AccountId=:acct];
system.debug(conts);
}
}

I have added the vf page as section in the opportunity layout. i am passing the accountid from opportunity and query the contact corresponding to the account and displaying the list of contact in the standard opportunity layout as inline vf section.but i am not get any contact values.kindly help me to solve this.

Best Answer

The reason for your problem is that you aren't adhering to the VF page order of execution.

Specifically #2 and #3 below:

  1. The constructor methods on the associated custom controller or controller extension classes are called, instantiating the controller objects.

  2. If the page contains any custom components, they are created and the constructor methods on any associated custom controllers or controller extensions are executed. If attributes are set on the custom component using expressions, the expressions are evaluated after the constructors are evaluated.

  3. The page then executes any assignTo attributes on any custom components on the page. After the assignTo methods are executed, expressions are evaluated, the action attribute on the component is evaluated, and all other method calls, such as getting or setting a property value, are made.

  4. If the page contains an component, all of the information necessary to maintain the state of the database between page requests is saved as an encrypted view state. The view state is updated whenever the page is updated.

  5. The resulting HTML is sent to the browser. If there are any client-side technologies on the page, such as JavaScript, the browser executes them.

The attribute componentValue is assigned to the custom component controller property acct after the constructor is evaluated.

Hence, @VamsiKrishna is correct in his second comment - you need to do this:

public List<Contact> conts {
   get {return [select id, Name, Email, Phone from Contact where AccountId=:acct] ;
   }
   set;
}

and the constructor should be:

public void componenttest() {}

There are lots of good reasons why VF controller constructors should be as simple as possible and data fetched using idempotent properties

As an aside, variable acct should more be more properly named acctId as it is of type ID and acct normally implies an Sobject.