Originally I wanted to attempt using the interface
notation as an added layer of abstraction for this project for the time being I’m going with what I believed to be a simpler solution, unfortunately I’m having issues.
The problem is my getter/setter variables are not working properly (at least as I understand them to work). Here’s the code breakdown:
Visualforce Page:
<c:Gauge widget-type="Number" report="Report Name" data-key="T!T" />
Visualforce Component:
<apex:component controller="GaugeController"> <!-- Define Component Attributes --> <apex:attribute name="widget-type" assignTo="{!type}" description="Type of gauge to be used" type="String" required="true"/> <apex:attribute name="report" assignTo="{!reportName}" description="Name report data to be used" type="String" required="true"/> <apex:attribute name="data-key" assignTo="{!key}" description="Field or column key used from the DataDetail" type="String" required="true"/> <!-- Define Component Body Variables --> <apex:variable var="result" value="{!reportName}"/> <!-- Define Component --> <apex:outputPanel> <apex:outputText>{!result}</apex:outputText> </apex:outputPanel> <apex:componentBody /> </apex:component>
Component Controller:
public class GaugeController extends Widget{ public String key { get; set; } /* Construtor */ public GaugeController() { System.debug(reportName); //returns NULL } }
Abstract Base Class:
public abstract class Widget implements Data{ //========= SETUP GETTERS/SETTERS ============// public String title { get; set; } public String type { get; set; } public String reportName { get; set; } public Widget() { System.debug(reportName); // returns NULL } }
I don’t understand why my System.debugs
show NULL
values yet the page gives me the String result I passed as expected. I think I need to be enlightened a little. Any and all help is much appreciated 🙂
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
The use of an abstract base class in itself should not cause issue. I think the problem here is bigger.
Visualforce Component getters / setters / constructors have an unusual and extremely lax contract with each other. I think the component controller code is subject to all the following ambiguities:
- setter order is non-deterministic
- getter order is non-deterministic
- construction order is non-deterministic
Unlike Visualforce Pages, which offer an action
attribute to give you a second bite at the cherry, you are basically out of luck relying on any kind of ordering with Visualforce Components.
The only thing that is guaranteed is that a property is set
before you get
it.
Reliability can be achieved by combining all the input parameters into one “super attribute” which is manipulated in a setter, and overwrites itself with the end result. Falling back to the Object
primitive reconciles the restraints in the visualforce output layer, while allowing the Apex code to still execute as needed.
I know it sounds far fetched. And I’d be very grateful if anyone can demonstrate reliability some other way. Below, you can see how your component might be re-written to the above ends 🙂
Visualforce Page
<c:Gauge TypeReportKey="Number,Name,T!T" />
Visualforce Component
<apex:component controller="GaugeController"> <!-- Define Component Attributes --> <apex:attribute name="TypeReportKey" assignTo="{!Params}" description="Type of gauge to be used, Name report data to be used, Field or column key used from the DataDetail" type="Object" required="true" /> <!-- Define Component Body Variables --> <apex:variable var="result" value="{!Params}"/> <!-- Define Component --> <apex:outputPanel> <apex:outputText>{!result}</apex:outputText> </apex:outputPanel> <apex:componentBody /> </apex:component>
Component Controller
public class GaugeController { public Object Params; public void setParams(Object value) { String type = ((String)value).split(',')[0]; String report = ((String)value).split(',')[1]; String key = ((String)value).split(',')[2]; this.Params = someWidgetFunction(type, report, key); } public Object getParams() { return this.Params; } }
(The insanity is contained within the setter…
someWidgetFunction
is where your code goes)
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0