So I have been working with components lately and have been pretty aggravated that I couldn't seem to get the assignTo to work correctly. So I followed the example showen in the documentation (Custom Component Controllers) word for word, and it worked.. but not really. Once I tried switching the get/set to the way I prefer public String controllerValue {get; set;} it stopped working. I also noticed that if I was to put anything in the constructor it access it, it would create a null error. For example, if you were to use the same example as in the documentation and changed the class to:
public with sharing class sgf_ComponentAssignToIssue {
public String controllerValue;
public void setControllerValue (String s) {
controllerValue = s.toUpperCase();
}
public String getControllerValue() {
return controllerValue;
}
public sgf_ComponentAssignToIssue() {
if (String.isNotBlank(controllerValue)) {
controllerValue.toLowerCase();
return;
}
ApexPages.addMessage(new ApexPages.Message(
ApexPages.Severity.ERROR,
'string is blank'
));
}
}
and change the page to:
<apex:component controller="sgf_ComponentAssignToIssue">
<apex:attribute name="componentValue" description="Attribute on the component." type="String" required="required" assignTo="{!controllerValue}" />
<apex:pageBlock title="My Custom Component">
<p>
<code>componentValue</code> is "{!componentValue}"
<br/>
<code>controllerValue</code> is "{!controllerValue}"
</p>
</apex:pageBlock>
Notice that the controllerValue has been upper cased using an Apex method.
<!-- just adding the following -->
<br />
<apex:pageMessages id="messages" />
</apex:component>
the page will error:
If I change the class to:
public with sharing class sgf_ComponentAssignToIssue {
public String controllerValue {
get {return controllerValue.toUpperCase();}
set;
}
public sgf_ComponentAssignToIssue() {
if (String.isNotBlank(controllerValue)) {
controllerValue.toLowerCase();
return;
}
ApexPages.addMessage(new ApexPages.Message(
ApexPages.Severity.ERROR,
'string is blank'
));
}
}
and leave the page as is, the page will now error:
If I change it so the class looks like this:
public with sharing class sgf_ComponentAssignToIssue {
public String controllerValue {
get;
set {controllerValue = value.toUpperCase();}
}
public sgf_ComponentAssignToIssue() {
if (String.isNotBlank(controllerValue)) {
controllerValue.toLowerCase();
return;
}
ApexPages.addMessage(new ApexPages.Message(
ApexPages.Severity.ERROR,
'string is blank'
));
}
}
The page will work again, but still nothing works in the constructor. And if I change it to say, an Id and update the class to:
public with sharing class sgf_ComponentAssignToIssue {
public Id controllerValue {get; set;}
public Account passedAccount {get; set;}
public sgf_ComponentAssignToIssue() {
if (String.isNotBlank((String)controllerValue)) {
passedAccount = new Account(Id = controllerValue);
return;
}
ApexPages.addMessage(new ApexPages.Message(
ApexPages.Severity.ERROR,
'Id is blank'
));
}
}
and the page to pass the Id to the controller, you get:
So you can see that the controller does effect the variable but still since I can not use it in the constructor I cant really use it in the component to do anything on load...
My Question is:
Why cant the class constructor or the getter access the variable being passed from the assignTo?
Labels
apex
(17)
salesforce
(15)
code
(11)
force.com
(11)
best practices
(7)
visualforce
(7)
Artical
(6)
class
(6)
method
(6)
sObject
(6)
tricks
(6)
JS
(5)
SOQL
(5)
tips
(5)
visualforce pages
(5)
helper
(4)
jQuery
(4)
manament
(4)
methods
(4)
101
(3)
CSS
(3)
clases
(3)
classes
(3)
queue
(3)
support
(3)
tablesorter
(3)
Cases
(2)
Contact
(2)
HTML5
(2)
Knowledge Base
(2)
Maps
(2)
Object
(2)
benchmark test
(2)
bug
(2)
challenge
(2)
knowledge
(2)
sites
(2)
style
(2)
user lists
(2)
8 bit
(1)
CSS3
(1)
Canvas
(1)
Comcast
(1)
DataCategories
(1)
Google
(1)
HTML
(1)
JavaScript
(1)
K.I.S.S.
(1)
Keep it simple stupid
(1)
Mario
(1)
Prevent duplicate
(1)
Resources
(1)
SOSL
(1)
Speed
(1)
UX
(1)
Usability
(1)
User interface
(1)
User org shart
(1)
Xfinity
(1)
apex:commandButton
(1)
apex:repeat
(1)
apex:selectCheckboxes
(1)
apex:selectList
(1)
assignTo
(1)
attachments
(1)
batman
(1)
cloudspokes
(1)
component
(1)
controllers
(1)
debug
(1)
debugging
(1)
efficiency
(1)
errors
(1)
for-loop
(1)
gif
(1)
google visualization
(1)
how to
(1)
images
(1)
issue
(1)
jpg
(1)
kiss
(1)
language
(1)
logo
(1)
methodology
(1)
multi-lingual
(1)
no images
(1)
null
(1)
photo
(1)
related list
(1)
rounded
(1)
rounded corners
(1)
set
(1)
spring'11
(1)
standardstylesheets
(1)
static Resources
(1)
system
(1)
test class
(1)
testing
(1)
trigger
(1)
troubleshooting
(1)
user prompt
(1)
variable
(1)
Showing posts with label bug. Show all posts
Showing posts with label bug. Show all posts
Tuesday, June 18, 2013
Monday, May 27, 2013
Bug with apex:selectCheckboxes
The Project:
I posted a simpler test of this not working here: Stackoverflow
**Update**
ANSWER FOUND and so not a bug lol bellow is the update made to the controller, and no update was needed to the page(see page at top of post for code):
public class sfg_testBugWithActionButton {
public List<String> fGender {get; set;}
public List<String> fGrade {get; set;}
public List<String> fRole {get; set;}
public String resultString {get; set;}
public Map<String, List<SelectOption>> filterMap {get; set;}
//this had to changed from Map<String, String> to what you see below
public Map<String, List<String>> filterKeys {get; set;}
public sfg_testBugWithActionButton() {
//this was also added, and helped make it all work
fGender = new List<String>();
fGrade = new List<String>();
fRole = new List<String>();
// and so this got updated as well to use the param and not a string
filterKeys = new Map<String, List<String>> {
'Gender' => fGender,
'Grade' => fGrade,
'Role' => fRole
};
createfilterMap();
resultString = 'on Load of page';
}
public PageReference preformAction() {
resultString = 'button action preformed';
return null;
}
private void createfilterMap() {
filterMap = new Map<String, List<SelectOption>>();
List<SelectOption> options = new List<SelectOption>();
for (String s : filterKeys.keySet()) {
if (s == 'Gender') {
options = new List<SelectOption>();
options.add(new SelectOption('Male', 'Male'));
options.add(new SelectOption('Female', 'Female'));
filterMap.put('Gender', options);
}
if (s == 'Grade') {
options = new List<SelectOption>();
options.add(new SelectOption('A', 'A'));
options.add(new SelectOption('B', 'B'));
options.add(new SelectOption('C', 'C'));
filterMap.put('Grade', options);
}
if (s == 'Role') {
options = new List<SelectOption>();
options.add(new SelectOption('Support', 'Support'));
options.add(new SelectOption('Sales', 'Sales'));
options.add(new SelectOption('Marketing', 'Marketing'));
filterMap.put('Role', options);
}
}
}
}
HAZA! :-)
Make a search with multi-select checkboxes for better filtering.
The Solution:
Simple right? Just make a page and controller with some <apex:selectCheckboxes> and a <apex:commandButton> to make it all go.
<apex:page showHeader="true" sidebar="true" controller="sfg_testBugWithActionButton">
<apex:form>
<apex:outputpanel id="mainWrap">
<apex:repeat value="{!filterMap}" var="key">
<div class="filterItem">
<h2>{!key}</h2>
<apex:selectCheckboxes value="{!filterKeys[key]}" layout="pageDirection">
<apex:selectOptions value="{!filterMap[key]}" />
</apex:selectCheckboxes>
</div>
</apex:repeat>
<apex:commandButton action="{!preformAction}" rerender="renderWrap" value="Submit Action" />
<apex:outputpanel id="renderWrap">
{!resultString}
</apex:outputpanel>
</apex:outputpanel>
</apex:form>
</apex:page>
public class sfg_testBugWithActionButton {
public List<String> fGender {get; set;}
public List<String> fGrade {get; set;}
public List<String> fRole {get; set;}
public String resultString {get; set;}
public Map<String, List<SelectOption>> filterMap {get; set;}
public Map<String, String> filterKeys {get; set;}
public sfg_testBugWithActionButton() {
filterKeys = new Map<String, String> {
'Gender' => 'fGender',
'Grade' => 'fGrade',
'Role' => 'fRole'
};
createfilterMap();
resultString = 'on Load of page';
}
public PageReference preformAction() {
resultString = 'button action preformed';
return null;
}
private void createfilterMap() {
filterMap = new Map<String, List<SelectOption>>();
List<SelectOption> options = new List<SelectOption>();
for (String s : filterKeys.keySet()) {
if (s == 'Gender') {
options = new List<SelectOption>();
options.add(new SelectOption('Male', 'Male'));
options.add(new SelectOption('Female', 'Female'));
filterMap.put('Gender', options);
}
if (s == 'Grade') {
options = new List<SelectOption>();
options.add(new SelectOption('A', 'A'));
options.add(new SelectOption('B', 'B'));
options.add(new SelectOption('C', 'C'));
filterMap.put('Grade', options);
}
if (s == 'Role') {
options = new List<SelectOption>();
options.add(new SelectOption('Support', 'Support'));
options.add(new SelectOption('Sales', 'Sales'));
options.add(new SelectOption('Marketing', 'Marketing'));
filterMap.put('Role', options);
}
}
}
}
(no style so nothing pretty, just to get the idea)
But WAIT! Why isn't anything happening when I click the button? The text next to the button should be changing. hummm Lets put a debug at the top of the method being called by the button and check the logs to see if its hit...
public PageReference preformAction() {
system.debug('Gender: ' + fGender);
system.debug('Grade: ' + fGrade);
system.debug('Role: ' + fRole);
resultString = 'button action preformed';
return null;
}
hummm nothing.. not even a mention of the button getting clicked in the logs, let alone my debug statements. Ok I know from experience I can force the button by using the <apex:actionRegion> attribute..
<apex:actionRegion>
<apex:commandButton action="{!preformAction}" rerender="renderWrap" value="Submit Action" />
</apex:actionRegion>
Click and well now the debug statement is being hit, but its not picking up the values in the <apex:selectCheckboxes> hummmm.. I know I shouldnt need the <apex:actionRegion> so lets remove that and see what happens when i just click the button, without selecting any of the checkboxes first.. Oh shit it works... the values are null, but they should be since nothing is selected.. Ok lets try changing the <apex:selectCheckboxes> to <apex:selectList> and see if they work.. damn, it seems to work, the resultsString is getting updated, but the values are still showing as null in the logs so I guess its not working, but atleast its working better than the <apex:selectCheckboxes>..
It shouldn't be anything to do with the maps or repeat but why dont we do this the long way and see if that helps..
<apex:page showHeader="true" sidebar="true" controller="sfg_testBugWithActionButton">
<apex:form>
<apex:outputpanel id="mainWrap">
<div class="filterItem">
<h2>Grade</h2>
<apex:selectCheckboxes value="{!fGrade}" layout="pageDirection">
<apex:selectOptions value="{!soGrade}" />
</apex:selectCheckboxes>
</div>
<div class="filterItem">
<h2>Gender</h2>
<apex:selectCheckboxes value="{!fGender}" layout="pageDirection">
<apex:selectOptions value="{!soGender}" />
</apex:selectCheckboxes>
</div>
<div class="filterItem">
<h2>Role</h2>
<apex:selectCheckboxes value="{!fRole}" layout="pageDirection">
<apex:selectOptions value="{!soRole}" />
</apex:selectCheckboxes>
</div>
<apex:commandButton action="{!preformAction}" rerender="renderWrap" value="Submit Action" />
<apex:outputpanel id="renderWrap">
{!resultString}
</apex:outputpanel>
</apex:outputpanel>
</apex:form>
</apex:page>
public class sfg_testBugWithActionButton {
public String fGender {get; set;}
public String fGrade {get; set;}
public String fRole {get; set;}
public List<SelectOption> soGender {get; set;}
public List<SelectOption> soGrade {get; set;}
public List<SelectOption> soRole {get; set;}
public String resultString {get; set;}
public sfg_testBugWithActionButton() {
createfilterMap();
resultString = 'on Load of page';
}
public PageReference preformAction() {
system.debug('Gender: ' + fGender);
system.debug('Grade: ' + fGrade);
system.debug('Role: ' + fRole);
resultString = 'button action preformed';
return null;
}
private void createfilterMap() {
soGender = new List<SelectOption>();
soGender.add(new SelectOption('Male', 'Male'));
soGender.add(new SelectOption('Female', 'Female'));
soGrade = new List<SelectOption>();
soGrade.add(new SelectOption('A', 'A'));
soGrade.add(new SelectOption('B', 'B'));
soGrade.add(new SelectOption('C', 'C'));
soRole = new List<SelectOption>();
soRole.add(new SelectOption('Support', 'Support'));
soRole.add(new SelectOption('Sales', 'Sales'));
soRole.add(new SelectOption('Marketing', 'Marketing'));
}
}
No joy, same problem with or without the repeat when using <apex:selectCheckboxes>. Now lets try the same thing but with <apex:selectList> instead.. And it works! But why wouldn't it work when in the repeat or with the <apex:selectCheckboxes>? I also made sure it works when I added the attribute multiselect="true" to them, since that is what I would need anyhow if I had to use Lists over checkboxes.
So lets review:
Right now it seems that anything with the <apex:selectCheckboxes> wont work (regardless of version since I did try bumping it back on both the page and controller). When trying to be dynamic and using a repeat to populate the Lists it fails as well for both <apex:selectCheckboxes> and <apex:selectList>. But if you do it the long way, you can get <apex:selectList> to work at the very least, although that means more fighting with style to get it to look like checkboxes if that is the desired effect.
*sad panda*
I posted a simpler test of this not working here: Stackoverflow
**Update**
ANSWER FOUND and so not a bug lol bellow is the update made to the controller, and no update was needed to the page(see page at top of post for code):
public class sfg_testBugWithActionButton {
public List<String> fGender {get; set;}
public List<String> fGrade {get; set;}
public List<String> fRole {get; set;}
public String resultString {get; set;}
public Map<String, List<SelectOption>> filterMap {get; set;}
//this had to changed from Map<String, String> to what you see below
public Map<String, List<String>> filterKeys {get; set;}
public sfg_testBugWithActionButton() {
//this was also added, and helped make it all work
fGender = new List<String>();
fGrade = new List<String>();
fRole = new List<String>();
// and so this got updated as well to use the param and not a string
filterKeys = new Map<String, List<String>> {
'Gender' => fGender,
'Grade' => fGrade,
'Role' => fRole
};
createfilterMap();
resultString = 'on Load of page';
}
public PageReference preformAction() {
resultString = 'button action preformed';
return null;
}
private void createfilterMap() {
filterMap = new Map<String, List<SelectOption>>();
List<SelectOption> options = new List<SelectOption>();
for (String s : filterKeys.keySet()) {
if (s == 'Gender') {
options = new List<SelectOption>();
options.add(new SelectOption('Male', 'Male'));
options.add(new SelectOption('Female', 'Female'));
filterMap.put('Gender', options);
}
if (s == 'Grade') {
options = new List<SelectOption>();
options.add(new SelectOption('A', 'A'));
options.add(new SelectOption('B', 'B'));
options.add(new SelectOption('C', 'C'));
filterMap.put('Grade', options);
}
if (s == 'Role') {
options = new List<SelectOption>();
options.add(new SelectOption('Support', 'Support'));
options.add(new SelectOption('Sales', 'Sales'));
options.add(new SelectOption('Marketing', 'Marketing'));
filterMap.put('Role', options);
}
}
}
}
HAZA! :-)
Labels:
apex,
apex:commandButton,
apex:selectCheckboxes,
apex:selectList,
benchmark test,
bug,
class,
code,
debug,
Maps,
method,
salesforce,
system,
visualforce,
visualforce pages
Subscribe to:
Posts (Atom)