I know that this is how to save a record
<apex:commandButton action="{!save}" value="Save"/>
I want a button to NOT save the current record (ie. Cancel) and navigate to the list of saved record (ie. list of objects for that object type).
Something like this...
<apex:commandButton action="{!cancel}" value="Cancel"/>
The list view for an object is your base URL / the 3 letter prefix for your object / o, for example:
https://na1.salesforce.com/a0C/o
So you could just create an action method that returns a Pagereference with the appropriate URL and set to redirect (pr.setRedirect(true)).
Alternatively, you could use your controller as an extension to a standard controller, and just call cancel on the standard controller:
// controller extension
public class TimeSheetExtension
{
ApexPages.standardController m_sc = null;
public TimeSheetExtension(ApexPages.standardController sc)
{
m_sc = sc;
}
public PageReference doCancel()
{
return m_sc.cancel();
}
}
// page
<apex:commandButton action="{!doCancel}" value="Cancel"/>
Note that this doesn't necessarily take you to the list view, it'll return you to the last page you were viewing before going to the VF page.
You should also add the immediate tag to your Cancel button, so that the form doesn't run any validation before performing the Cancel operation.
<apex:commandButton action="{!cancel}" immediate="true" value="Cancel"/>
See http://blogs.developerforce.com/developer-relations/2008/12/using-the-immediate-attribute-on-commandlinks-and-commandbuttons.html
While applying cancel operation visualforce you should stop the form validation.Use below any one methods to stop the form validation based on your requirements.
Method 1:
Using
html-5 in doctype in visualforce page
means you should use html-formnovalidate and immediate in cancel button. For example
<apex:commandButton action="{!cancel}" value="Cancel" immediate="true"
html-formnovalidate="formnovalidate" />
Method 2:
you should use immediate key word only need for stopping form validation. For Example
<apex:commandButton action="{!cancel}" value="Cancel" immediate="true"/>
One of the other answers suggested calling the standard controller's cancel action so I want to expand on that since it led me in the direction to solve my similar problem.
If you want to cancel an edit as an ajax request without refreshing the whole page, declare the action as void and don't return the page reference, but still call the 'cancel' action on the standard controll. Make sure the command button specifies the rerender attribute.
// controller extension
public class TimeSheetExtension
{
ApexPages.standardController m_sc = null;
public TimeSheetExtension(ApexPages.standardController sc)
{
m_sc = sc;
}
public void doCancel()
{
m_sc.cancel();
}
}
// page
<apex:commandButton action="{!doCancel}" value="Cancel" rerender="container_id"/>
Related
I have done a lot of research on this, and can not figure out the best way to solve this. I am trying to prevent a user from clicking multiple times on a custom button in a VF page. When that is done, they invoke the method related to the button multiple times. I saw quite a few posts with different solutions, but most of them are on posts from 5-10 years ago.
<script src="//ajax.googleapis.com/ajax/libs/jquery/latest/jquery.js"></script>
<script>
function buttonsEnabled(enabled) {
// retrieve all of the buttons or links on the page
// with the css class of btn
var $buttons = jQuery('.btn');
if (enabled === false) {
// add the btnDisabled class to give it the look of being disabled
// add the disabled attribute to actually disable interactability
$buttons.toggleClass('btnDisabled', true).attr('disabled', 'disabled');
} else {
// remove the css class and the disabled attribute
$buttons.toggleClass('btnDisabled', false).attr('disabled', null);
}
}
function doSomeWork() {
// first, call the action function to post the form
doSomeWorkActionFunction();
// second, disable the buttons
buttonsEnabled(false);
// third, return false to prevent the click from
// posting the form a second time
return false;
}
</script>
<apex:form>
<apex:actionFunction name="doSomeWorkActionFunction"
action="{!yourControllerMethod}"
oncomplete="buttonsEnabled(true);"
rerender="whateverYouNeedToRerender"></apex:actionFunction>
<apex:commandLink action="{!yourControllerMethod}"
value="Your Text Here"
id="theCommandLink"
onclick="return doSomeWork();" />
</apex:form>
I have a visualforce page that has a picklist called Topic and sometimes I will need to select one of the picklist options upon page load (meaning the Topic will be passed on from another page and will need to be selected upon loading the page for the first time). I'm not sure how to do this? I'm posting part of the Visualforce page that handles topic selection and the Controller code that below. Any help would be appreciated.Thanks.
Visualforce page:
<!---------------------------------- Select Topic ----------------------------------------------------->
<apex:pageblockSection title="Select the Topic" >
<apex:selectList value="{!topic}" size="1">
<apex:outputlabel for="Topic" value="Pick a Topic :" ></apex:outputlabel>
<apex:selectOptions id="topic" value="{!Topics}"/>
<apex:actionSupport action="{!populateParameters}" reRender="parametersSection,querySection" event="onchange"/>
</apex:selectList>
</apex:pageblockSection>
<!---------------------------------- End of Select Topic ---------------------------->
<!---------------------------------- Parameters for Topic ----------------------------------------------------->
<apex:pageblockSection id="parametersSection" title="Input Parameters">
<apex:repeat value="{!topicpParamWrapperList}" var="params">
<apex:outputPanel >
<apex:outputlabel value="{!params.parameter.Name}" ></apex:outputlabel>
<apex:inputfield value="{!params.parameter.inputValue__c}" rendered="{!params.renderAsText}">
<apex:actionsupport action="{!placeValuesInQuery}" reRender="querySection,splunUrlLink" event="onchange"/>
</apex:inputfield>
<apex:inputfield value="{!params.parameter.DateTimeValueHolder__c}" rendered="{!params.renderAsDate}">
<apex:actionsupport action="{!placeValuesInQuery}" reRender="querySection,splunUrlLink" event="onchange"/>
</apex:inputfield>
</apex:outputPanel>
</apex:repeat>
</apex:pageblockSection>
<!---------------------------------- End of Parameters for Topic ----------------------------------------------------->
Apex Controller
public List < topicpParamWrapper > topicpParamWrapperList {
get;
set;
} {
topicpParamWrapperList = new List < topicpParamWrapper >();
}
public void populateParameters()
{
if(!topicpParamWrapperList.isEmpty())
{
topicpParamWrapperList.clear();
}
if(topic!='' && topic!=Null)
{
for(Query_Parameter__c qParam :[select id, Parameters__r.Variable_Name__c, Parameters__r.Type__c,Parameters__r.Name from Query_Parameter__c where Topics__c=:topic])
{
Parameters__c param = new Parameters__c();
param.Name =qParam.Parameters__r.Name ;
param.type__c = qParam.Parameters__r.type__c;
param.Variable_Name__c=qParam.Parameters__r.Variable_Name__c;
topicpParamWrapperList.add(new topicpParamWrapper(param));
}
getQueryToRun();
}
}
public void getqueryToRun(){
if(mapTopics.containsKey(topic))
{
this.queryToRun =mapTopics.get(topic).query__c;
this.queryMain=mapTopics.get(topic).query__c;
}
}
public List < topicpParamWrapper > paramList {
get;
set;
} {
paramList = new List <topicpParamWrapper>();
}
All you really have to do is to set the topic to some initial value in the constructor (the special function that has name identical to class' name). You set it to some value and then it'll be rendered properly in visualforce (assuming same value is one of the selectable options!).
You have omitted the constructor or <apex:page> tag so we don't know how you're navigating to that page. But probably easiest for you would be to pass the topic in the URL. So if you access the page like that:
/apex/MyPage?topic=Something, something
then in the constructor you could do this:
topic = ApexPages.currentPage().getParameters().get('topic');
(the name of the URL parameter doesn't have to be same as the variable name but it makes sense to have them at least similar)
You can read more about getParameters()
If there is risk that your topic will contain &, spaces etc you probably should URLENCODE it when building the link.
I have a page that needs to pass data to another page. They both use the same controller, but the second page has its own controller extension. When the first page passes data to the second page, the second page will recall the constructor of the controller. If I remove the controller extension from the second page, data can be passed and the constructor is only called on the first page, not on the second.
How can I pass state from one page to another, if both pages use the same controller, but one page uses a controller extension?
For example, in the following code, if I enter data in the outputText for the variable t and then go to the next page, the state won't save, the constructor will be recalled, and the value for t on page 2 will be "construct". If the testExtension is removed from the second page, then everything works fine.
apex/test1
VisualForce
<apex:page controller="test">
<apex:outputText value="{!t}" />
<apex:commandButton action="/test2" value="Go to test2" />
</apex:page>
Controller
class test {
public String t {get; set;}
public test() {
t = 'construct';
}
}
apex/test2 VisaulForce
<apex:page controller="test" extension="testExtension">
<apex:outputLabel value="{!t}" />
</apex:page>
controller extension:
class testExtension {
public testExtension(test controller) {
}
}
public with sharing class Fake01_Controller {
public String fake02String {get;set;}
public PageReference fake03Submit() {
PageReference prToNavigate = null;
prToNavigate = Page.Fake_02;
return prToNavigate;
}
}
Fake 01 page:
<apex:form >
<apex:inputText value="{!fake02String}" />
<apex:commandButton action="{!fake03Submit}"
value="Navigate to Fake 02"
/>
</apex:form>
Fake 02 page:
<apex:form >
<apex:outputText value="{!fake02String}" />
</apex:form>
Please, read PageReference about setRedirect method:
If set to false, the redirect is a server-side forward that preserves
the view state if and only if the target page uses the same controller
and contains the proper subset of extensions used by the source page.
class test {
public String t {get; set;}
public test() {
t = 'construct';
}
public PageReference test2() {
return page.test2;
}
}
<apex:page controller="test">
<apex:outputText value="{!t}" />
<apex:commandButton action="{!test2)" value="Go to test2" />
</apex:page>
I know that this is how to save a record
<apex:commandButton action="{!save}" value="Save"/>
Now I want a button to save the current record and reset the form to input another record.
Something like this...
<apex:commandButton action="{!SaveAndNew}" value="Save & New"/>
The URL for the new record page is the {org URL}/{3 letter object prefix}/e?".
You could define your save method as follows, where m_sc is a reference to the standardController passed to your extension in it's constructor:
public Pagereference doSaveAndNew()
{
SObject so = m_sc.getRecord();
upsert so;
string s = '/' + ('' + so.get('Id')).subString(0, 3) + '/e?';
ApexPages.addMessage(new ApexPages.message(ApexPages.Severity.Info, s));
return new Pagereference(s);
}
To use your controller as an extension, modify it's constructor to take a StandardController reference as an argument:
public class TimeSheetExtension
{
ApexPages.standardController m_sc = null;
public TimeSheetExtension(ApexPages.standardController sc)
{
m_sc = sc;
}
//etc.
Then just modify your <apex:page> tag in your page to reference it as an extension:
<apex:page standardController="Timesheet__c" extensions="TimeSheetExtension">
<apex:form >
<apex:pageMessages />
{!Timesheet__c.Name}
<apex:commandButton action="{!doCancel}" value="Cancel"/>
<apex:commandButton action="{!doSaveAndNew}" value="Save & New"/>
</apex:form>
</apex:page>
Note that you don't need Extension in the class name, I just did that to be sensible. You shouldn't need to modify anything else on your page to utilise this approach.
Ideally, you could use the ApexPages.Action class for this. But when I've tried to use it, it's been too buggy. It's been a while, so you might want to play with it using the {!URLFOR($Action.Account.New)} action.
What will work is simply using a PageReference to redirect the user to the "new" URL.
For example, if this were for Accounts,
public PageReference SaveAndNew() {
// code to do saving goes here
PageReference pageRef = new PageReference('/001/e');
return pageRef;
}
I'm having strange results with a Visualforce page (yes, Salesforce.com is icky, I know). My issue is that I am trying to use the inputField to bind data on a custom sObject, but in my custom controller, it is not recognizing the user input data.
Here is the code snippet from the page:
<apex:pageBlockSection title="Enter New Fee" rendered="{!isRenderedFees}" >
<apex:inputField value="{!workingFee.Fee_Type__c}" required="True"/>
<apex:inputField value="{!workingFee.Fee__c}" required="True"/>
<apex:pageBlockSectionItem >
<apex:CommandButton value="Save Fee" action="{!saveFee}" immediate="true" />
<apex:CommandButton value="Cancel" action="{!cancelFee}" immediate="true" />
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
and here is the code from the controller:
public Fee__c workingFee {get; set;}
....
public PageReference saveFee(){
this.workingFee.Trade_Group__c = tradeGroup.id;
try{
System.debug('~~~~#~~#~~workingFee: '+workingFee.Fee_Type__c +'='+workingFee.Fee__c);
upsert workingFee;
}catch (System.Dmlexception e){
ApexPages.addMessages(e);
return null;
}
System.debug('~~~~#~~#~~workingFee: '+workingFee.Fee_Type__c +'='+workingFee.Fee__c);
//savedFees.add(workingFee.clone());
//re-render the page
this.isRenderedFees = False;
return null;
}
I've made sure the workingFee property is not null. Whenever I hit the "Save Fee" button after entering the values, it reloads the page and gives me the message "Error: Required fields are missing: [Fee__c]" (note, Fee__c here is a currency field -- it's not that it expects this to be an sObject, is it?)
The debug statement in the saveFee() method shows that workingFee's important fields are null, when I would expect them to have been assigned the values input by the user.
I have had a whole heap of issues binding controls to a property exposed with the simple { get; set; } notation... The rest of your code will see the properties, but for some bizarre reason, your View won't (always) bind...
Try writing explicit get/set methods, like
private workingFee;
public Fee__c getWorkingFee() {
return workingFee;
}
public void setWorkingFee(Fee__c value) {
workingFee = value;
}
There is no logical reason why this should work any different to
public Fee__c workingFee { get; set; }
but in my experience, it sometimes does...
what did you say about it being icky? ;)
Immediate=false/true has bitten me quite a few times too. Good catch Ian.