apex:commandButton can't return nothing? - salesforce

I have:
<apex:commandButton action="{!whatever}" value="myButton" reRender="sectionX" />
And
public String whatever(){
return 'ok';
}
It doesn't work (returns 401 Unauthorized), but if I write:
public void whatever(){
// some code
}
works fine.
The question is: how can I return something (a JSON or a Page) to this call?
Thanks

CommandButtons are used to execute some code on the server and they return a PageReference, not a string/json value.
<apex:commandButton action="{!whatever}" value="myButton" reRender="sectionX" />
So the method whatever should do the work and then assign the result to a public property on the controller so the page can display the result.
The rerender attribute says to reload the data in the outputpanel sectionX. SectionX needs to enclose the results you want to display from the commandbutton action.
public class myController {
public string Result {get;set;}
public PageReference whatever() {
// do your work here
Result = DateTime.Now();
return null;
}
}
Visualforce
<apex:outputpanel id="sectionX">{!Result}</apex:outputpanel>
Every time you click myButton command button the outputpanel will display a new datetime string.
An afterthought: If you want to put a string result/JSON into a javascript method, you can do something like the following.
<script>
function processJSON(val) {
var res = JSON.parse(val);
// do your work here
}
</script>
<apex:outputpanel id="sectionX">
<script>
processJSON("{!Result}");
</script>
</apex:outputpanel>
In your example commandbutton code you used rerender so you dont need to return a non null PageReference. If, on the other hand, you want to go to another page when you click the commandbutton, you would not set the rerender attribute and you would need to return a non-null PageReference,
ie
public PageReference whatever() {
return Page.MyVisualforcePage;
}

Not realy. Look here
As for me, I used method which returns PageReference variable.
Better to do like this:
public PageReference whatever(){
PageReference pageRef = null; // null won't refresh page at all if I'm not mistaken
// some cool logic goes here
if(toNavigate) {
pageRef = new PageReference('here is some URL to which user must be navigated');
} else if(toRefreshCurrent) {
pageRef = ApexPages.currentPage();
}
return pageRef;
}
About returning page - look here.

Related

Create UI components on page load

I am currently working on oracle adf task flows and regions and I want to create and update some UI components on page load and for this I am using method call activity as default.The problem is that I am getting null values following is my code in the bean that executes on the method call.
package view;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import oracle.adf.view.rich.component.rich.output.RichOutputText;
public class testBean {
public testBean() {
}
public String testMethod() {
// Add event code here...
FacesContext facesContext = FacesContext.getCurrentInstance();
UIViewRoot root = facesContext.getViewRoot();
RichOutputText text = ( RichOutputText )root.findComponent( "r1:ot1" );
text.setValue( "Adding text on run time" );
return "product";
}
}
The set value method returning me null may be it is because the fragment product.jsff which is the view activity is not initiated and the output text with ot1 returning null.
The better approach to achieve the setting of value is to have a property in your bean say: textValue and then bind the value attribute of your ot1 with the property of the bean.
class TestBean{
private String textValue;
public String testMethod() {
textValue = "Adding text on run time";
}
public String getTextValue(){
return textValue;
}
}
Your JSPX would be:
<af:outputText id="ot1" value=#{beanName.textValue}" />

How can I pass variables state from one page to another, if both pages use the same controller, but the second page uses a controller extension?

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>

Adding External XML to a VisualForce DataTable/List

I am making an external call to a Server and returning XML (HTTPResponse). I then use a DOM parser to get a list of items.
How can I add the list of items to a DataTable/DataList?
How can I parse the XML structure into a Salesforce structure within the class itself?
Thank you
Hi eyesscream. All is working fine, except one thing. I needed to get deep in XML
Dom.XMLNode rootElement = doc.getRootElement();
for (Dom.XmlNode assets : rootElement.getChildElements()) {
if (assets.getName().trim() == 'models') {
for (Dom.XmlNode asset : assets.getChildElements()) {
if (asset.getName().trim() == 'model') {
for (Dom.XmlNode serial : asset.getChildElements()) {
if (serial.getName().trim() == 'modelNumber') {
text = serial.getText().trim();
allOptons.add(new SelectOption(text, text));
}
}
}
}
}
}
on VF page it duplicates the results. Why?
Go through your XML adding elements to a list of strings of wrapper objects if you need to store more than 1 parameter. Then such list can be assigned to dataTable, pageBlockTable, repeat etc tags without any problems. It's not like these tags work only on standard sObjects.
For a simple list of Strings with checkboxes you don't even need any helper classes.
public class StackXml{
public List<SelectOption> allOptions {get;private set;} // this will hold serial numbers for use in VF page.
// if you wouldn't plan to use VF with checkboxes, simple List<String> would be enough
public List<String> selectedOptions {get;set;}
public StackXml(){
allOptions = new List<SelectOption>();
selectedOptions = new List<String>();
String xmlString = '<serials><serialNumber>ver123</serialNumber><serialNumber>ver456 </serialNumber>' +
'<intrusion>something to prove it will be skipped</intrusion>' +
'<serialNumber>abc007</serialNumber></serials>';
Dom.Document doc = new Dom.Document();
doc.load(xmlString);
Dom.XMLNode rootElement = doc.getRootElement();
for(Dom.XmlNode node : rootElement.getChildElements()){
if(node.getName().trim() == 'serialNumber') {
String text = node.getText().trim();
allOptions.add(new SelectOption(text, text));
}
}
}
public void assign(){}
}
<apex:page controller="StackXml">
<apex:form>
<apex:selectCheckboxes value="{!selectedOptions}" layout="pageDirection">
<apex:selectOptions value="{!allOptions}"/>
</apex:selectCheckboxes>
<apex:commandButton value="Assign" action="{!assign}"/>
</apex:form>
<hr/>
<p>You have selected:</p>
<apex:dataList value="{!selectedOptions}" var="o">{!o}</apex:dataList>
</apex:page>

Unable to bind Component attribute with controller

I am trying to develop a visualforce custom component which takes an attribute from a visual force page. I need to access that attribute in controller's Constructor so that i can brings some records from database and i need to display those records in the Component. But problem is that i am not getting Attribute value in Controller.
See the below code to understand the problem clearly..
Controller :
public with sharing class AdditionalQuestionController {
public String CRFType {get;set;}
public AdditionalQuestionController () {
system.debug('CRFType : '+CRFType);
List<AdditoinalQuestion__c> lstAddQues = [Select AddQues__c from AdditoinalQuestion__c wehre CRFType = :CRFType];
system.debug('lstAddQue : '+lstAddQue);
}
}
Component :
<apex:component controller="AdditionalQuestionController" allowDML="true">
<apex:attribute name="CRFType" description="This is CRF Type." type="String" required="true" assignTo="{!CRFType}" />
<apex:repeat value="{!lstAddQue}" var="que">
{!que}<br />
</apex:repeat>
</apex:component>
VisualForce page :
<apex:page >
<c:AdditionalQuestionComponent CRFType="STE" />
</apex:page>
Thanks,
Vivek
I believe the issue here is that you're expecting the member variable to have a value inside the constructor — the snag is that the instance of the class is being constructed! It doesn't exist yet and so there is no way that a non-static member variable could be given a value prior.
Instead of doing the query in your constructor, specify your own getter for lstAddQue and do the query in there when you need the data. Of course, you may want to cache the value so that the query is not run every time, but from the looks of things that won't be relevant here.
Setter methods on the attributes in a VF component appear to be called after the constructor has returned, unfortunately. Here's an alternative solution for your controller that uses a getter method to populate your list (which would be called after your CRFType member variable has been set):
public with sharing class AdditionalQuestionController {
public String CRFType {set;}
public AdditionalQuestionController () {
system.debug('CRFType : '+CRFType); // this will be null in the constructor
}
public List<AdditoinalQuestion__c> getLstAddQue() {
system.debug('CRFType : '+CRFType); // this will now be set
List<AdditoinalQuestion__c> lstAddQues = [Select AddQues__c from AdditoinalQuestion__c wehre CRFType = :CRFType];
system.debug('lstAddQue : '+lstAddQue);
return lstAddQue;
}
}

How to implement "Save & New" functionality in a VisualForce 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;
}

Resources