6

I have multiple visualforce components that each have their own controller that is extended from a base abstract class. For example:

Visualforce Page:

<apex:page>
    <c:MyFirstComponent />
    <c:MySecondComponent />
...

MyFirstComponent 1:

<apex:component controller="MyFirstComponentController">

MyFirstComponentController Class:

public class MyFirstComponentController extends BaseController {

MySecondComponent 2:

<apex:component controller="MySecondComponentController">

MySecondComponentControllerClass:

public class MySecondComponentController extends BaseController {

BaseController :

public abstract class BaseController {
    BaseController(){
        getSomeData();  // Here's the problem
    }
}

Right now for every component instance on the page a BaseController instance is constructed causing the getSomeData() method to fire but this is not necessary considering the data is the same for all components on the page. What is the best way to avoid this?

I was thinking perhaps to remove the controller from the components themselves and instead add those controllers as extensions on the page which I would then pass their instance as an attribute to each component... but since each extension extends the BaseController I would still have duplicates for every component type I have on the page.

Is there a different structure I could use to allow for this without causing these redundancy issues?

1
  • +1 for titling the post such that it is likely to be found again by others with the same issue
    – cropredy
    Jan 16, 2016 at 0:37

1 Answer 1

6

I'd use a CommonDataController to pass this data around:

public class CommonDataController {
    public CommonDataController(ApexPages.StandardController controller) {
        getSomeData();
    }
    public CommonDataController getCommonData() {
        return this;
    }
    // getSomeData not relevant to this example, but should exist.
}

In your BaseController, provide a holding place for this:

public abstract class BaseController {
    protected CommonDataController commonData;
    public void setCommonDataController(CommonDataController data) {
        commonData = data;
    }
    public CommonDataController getCommonDataController() {
        return commonData;
    }
}

Then, your page just includes CommonDataController once:

<apex:page ... extensions="CommonDataController">
    ... <c:myWidget commonData="{!commonData}" /> ...

And each component uses that data:

<apex:component ...>
    <apex:attribute name="commonData" assignTo="{!commonDataController}" type="CommonDataController" description="..." required="true" />

At this point, you have non-static data populated from a common point that allows inter-component communications, shared data resources, etc. The constructor is called only once, and each extension class is provided access to the common data.

6
  • Getting the following error when attempting to deploy the component: Error: Read only property 'c:myWidget.commonDataController' Jan 15, 2016 at 22:36
  • @Xtremefaith It might need to be all marked up as global instead of public. I did have that problem previously.
    – sfdcfox
    Jan 15, 2016 at 22:42
  • I added global to the base controller class and replaced the protected commonData with global but still getting the read only property... Jan 15, 2016 at 22:52
  • 1
    @Xtremefaith Hold on. It's in my one of my dev orgs. I'll update this answer in a bit.
    – sfdcfox
    Jan 15, 2016 at 22:57
  • I switched commonData to public and added { get; set; } and now its working... Jan 15, 2016 at 23:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .