I have a Visualforce page that is essentially a form with 8 steps. It uses a custom controller. I have recently moved each step into it's own component (8 in total). Now what I am wondering is, can I use the visualforce page controller without having to call the controller again within each one of my components. When I call the controller in each component I receive the error: 'System.LimitException: Too many SOQL queries: 101'. when I omit the controller all together I also receive an error. The SOQL error was not present before I moved each step into it's own component.
1 Answer
I typically do this with the page controller directly:
<apex:page controller="XYZ">
<c:comp1 controller="{!self}" />
<c:comp2 controller="{!self}" />
</apex:page>
public class XYZ {
public XYZ getSelf() {
return this;
}
}
<apex:component controller="ABC">
<apex:attribute assignTo="{!pageController}" name="controller" type="XYZ" required="true" />
...
</apex:component>
public class ABC {
public XYZ pageController { get; set; }
...
}
This design can allow you to share data between all the components, typical if you're building a multi-page wizard, for example.
-
1@MAS89 I typed this from memory, might a typo somewhere. Check the docs for more info. I'll see if I can find a working version in my code base.– sfdcfoxJan 10, 2019 at 17:18
-
sfdcfox, in your answer you mentioned a multi-page wizard. I am curious if there are open examples of this on the Internet. I am building one and I am struggling with finding best practices on this.– EduardFeb 6, 2019 at 9:08
-
1@Eduard I created a gist (had to fix from previous one, had typos) that demonstrates the techniques outlined in this answer. The controller has the shared logic, and each component can access the data/methods. This is a super-simple example, but it does copy-paste well, so go ahead and check it out.– sfdcfoxFeb 6, 2019 at 13:13
-
sfdcfox, please bare with me one more question. In your example, data and methods from the controller are shared with components. In this question I saved the controller instance as member variable in components' controller. And this exposed weird behavior of View State. So is it really reasonable to build complex wizards when the main controller instance is passed to a component's controller?– EduardFeb 6, 2019 at 13:36
-
1@Eduard Yes, I agree that SoC is important. You can use the page-level controller strictly for data as well, and each component can have their own controller. The demo I wrote is primarily for, well, demonstration purposes. You seem to have a firm grasp on what your project needs now, so feel free to adjust the pattern as necessary.– sfdcfoxFeb 6, 2019 at 14:34