For some reason the second query in the constructor makes the Cancel button in my visualforce page not work. Does this have to do with some special quirk in PricebookEntry?
If you comment out the second query (the one that populates HwAndSwProducts) the cancel button works fine.
This is the controller:
public with sharing class ManageAddSupportController {
public Opportunity opp { get; private set; }
public List<PricebookEntry> HwAndSwProducts { get; private set; }
public ManageAddSupportController() {
//Populate controller properties
opp = [SELECT name, id, Pricebook2Id FROM Opportunity
WHERE Id =: ApexPages.currentPage().getParameters().get('id')];
//This is the query that if we comment out the Cancel works
HwAndSwProducts = [SELECT name, id, ProductCode, UnitPrice
FROM PricebookEntry WHERE Pricebook2Id =:opp.Pricebook2Id
AND (NOT name LIKE '%Service%')];
}
public PageReference cancelSupport() {
System.debug('we want to cancel!!!');
PageReference ref = new PageReference('/' + opp.Id);
ref.setRedirect(true);
return ref;
}
}
And this is the view:
<apex:page controller="ManageAddSupportController">
<h1>Opportunity {!opp.name}</h1>
<p>Please choose those products you'd like to add support to.</p>
<apex:form >
<div style="text-align:center">
<apex:commandButton action="{!cancelSupport}" value="Cancel" id="cancelAddSupport" />
</div>
<br/>
<apex:pageBlock >
<apex:pageBlockTable value="{!HwAndSwProducts}" var="product">
<apex:column style="width: 5%">
<apex:inputCheckbox value="{!product.Id}"/>
</apex:column>
<apex:column value="{!product.Name}"/>
<apex:column value="{!product.ProductCode}"/>
<apex:column value="{!product.UnitPrice}"/>
</apex:pageBlockTable>
</apex:pageBlock>
</apex:form>
When I add debugging statements in the cancel action I see that it's not even being called when that second query is present. If you look at the logs it seems like the constructor is being called again. Very strange...
Attribution to: ceiroa
Possible Suggestion/Solution #1
This "cancel" action (like any other button) is doing a postback to the controller. That's a lot of work (deserialize viewstate, perform basic checks on the data such as "were the fields marked as required actually filled in"...)
To bypass these checks use immediate="true"
in your commandButton. Furthermore - I don't think you even need the whole cancelSupport function. URLFOR will do - and less code to maintain and provide code coverage is always a good thing.
Combine these 2 for maximum performance ;)
<apex:commandButton
value="Cancel"
action="{!URLFOR($Action.Opportunity.View, opp.Id)}"
immediate="true" />
Being able to modify the link in future right in the VF page (without redeploying the Apex) is just an added bonus!
EDIT Why do you have a custom controller actually? This page looks like a candidate to have standardController="Opportunity"
. Then your job would be even easier, action="{!view}"
:)
Attribution to: eyescream
Possible Suggestion/Solution #2
This was a tricky one, adding this to the Visualforce page
<apex:pageMessages />
finally grassed up the culprit !
This is the offending binding :
<apex:inputCheckbox value="{!product.Id}"/>
You're binding a boolean to an Id field, which fails conversion at runtime.
Commenting out this line makes the Cancel button work just fine.
If you intend using a checkbox to select Products, make use of the wrapper pattern, where you can have a boolean instance variable for selection.
http://wiki.developerforce.com/page/Wrapper_Class
P.S. As for the mystery of why commenting out the second SOQL query makes it works - no Products selected, so no Runtime Exception converting Boolean to Id.
Attribution to: techtrekker
This content is remixed from stackoverflow or stackexchange. Please visit https://salesforce.stackexchange.com/questions/4241