function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
sf_evolutionsf_evolution 

MVC and controller communication

Hi all,

 

This is really just a request for information, but  it just seems like I'm making things way too hard on myself.

I typically use inputText boxes for date input, so that may be coloring what  sems to go on in my code.
Basically, I can't seem to get data from the VF page to the controller without using an apex:actionFunction.

For example, this APEX class has to have data and a method for processing the <apex:actionFunction> tag:

public class OpportunityHistoryController {
  ...
  public String From_Date {get;set;}  // 
  ...
  public void dateChange() {
      System.debug('DATECHANGE WAS MADE:');
      ...
    }

   ...

 And next, the VF page markup calls the controller function:

<apex:page controller="OpportunityHistoryController" id="opportunityHistPage">
<apex:form id="OpportunityForm">
<script>
function DynamicDatePicker(d_id) {
 DatePicker.pickDate(false,d_id.id,false);
 dateChange(d_id);
 }
function checkDateFormat() {}
</script>
   <apex:pageBlock title="Opportunity History Statement" id="pb1">
    
    <apex:actionFunction action="{!dateChange}" reRender="condisplay" name="dateChange">
     <apex:param value="" assignTo="{!dummy}" name="assignvalue"/>
    </apex:actionFunction>
     
    From: <apex:inputText value="{!From_Date}" id="f" onfocus="DynamicDatePicker(this);" onchange="checkDateFormat(this.id);" onblur="setFocusOnLoad()" size="20" disabled="false"/>

     ...

 Now, why the <apex:actionFunction> is needed, I have no clue - all I know is that most of my code seems to not update values between the page and the controller unless there is some linkage between the two.  In fact, the "dateChange()" function in the controller doesn't really have to do anything - it just has to be present.

My suspicion is there is something going on with the MVC architecture with SFDC that is necessitating this "connection" between the two to notify the controller that the VF page is "dirty" - If anyone has a documentation reference on other ways to do this, I'd very much appreciate it.

Similarly, with SelectLists, I seem to have to make up similar coding  -

For instance, Taking the OpportunityHistoryController example I'm messing with above, and add the following subroutines:

public class OpportunityHistoryController {
  ...
        public  Map<id,UserRole> maplstroles{get;set;}
        public UserRole theRole {get;set;}  // Role ID
        ...
        public OpportunityHistoryController() {
	    ...
	    maplstroles = new Map<id,UserRole>();            
    	    }

	// build Role SelectOptions
        public List<SelectOption> getRolesLst(){
           System.debug('Entering getRolesLst');
           options.clear();
           options.add(new selectOption('--None--','-- Select Role --'));
           for(UserRole rx:[SELECT ID, Name From UserRole  ORDER BY Name ASC]){
             options.add(new selectOption(rx.id,rx.name));
             maplstroles.put(rx.id,rx);
             }
           return options;
           }


	 // process the "apex:actionFunction " call...
	 public void RoleID() {
	    System.debug('getting roleID for: ' + rid);
	    theRole =  maplstroles.get(rid);
	    System.debug('theRole.Id: ' + theRole.Id);
	    System.debug('theRole.Name: ' + theRole.Name);
	    }

 ...And somewhere in the VF markup, I want to update the apex page:

<apex:page controller="OpportunityHistoryController" id="opportunityHistPage">
<apex:form id="OpportunityForm">
<script>
function callactionfun(picklistval){
   change(picklistval);
   }
</script>
  ...
   <apex:pageBlock title="Opportunity History Statement" id="pb1">
    ...
    <apex:actionFunction action="{!RoleID}" reRender="condisplay" name="change">
     <apex:param value="" assignTo="{!rid}" name="assignvalue"/>
    </apex:actionFunction>

     ...
     
    <apex:selectList value="{!rid}" multiselect="false" size="1"  
    			onchange="callactionfun(this.options[this.selectedIndex]);" >
        <apex:selectOptions value="{!RolesLst}"/>
    </apex:selectList>

...

 ...It's really just a personal opinion, but it looks like SFDC is following more of the "MVVC" model - where we basically have to notify the controller of changes that occur on the view.   

Sorry, but I'm still doing research on this.  
But if anyone has ideas about how to make coding for dynamic input easier, I'd appreciate it.

 

 

 

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
Cory CowgillCory Cowgill

Finally if you use CommandButton and invoke an action the ViewState is of course passed along back to the Server and your method will execute with information updated in the ViewLayer.

 

Perhaps this will help:

http://wiki.developerforce.com/page/An_Introduction_to_Visualforce_View_State

All Answers

admintrmpadmintrmp
I don't understand your thinking here. Why would you need to call actionFunction? I've never had to do what you seem to be doing here.

I can write a simple form with an inputField for a value. When you invoke an action via a commandButton or commandLink, that data is then saved to that property in the class.

I'm not sure if you are over-complicating the whole thing or I have you wrong in the first place about what you are trying to achieve.
sf_evolutionsf_evolution

Hi

 

It seem like when I have a VF page with a custom controller all input from the user doesn't get updated in the controller unless I have an actionfunction.

 

Things seem to work better if on the VF page I'm updating SObjects.

class data and/or public primary-type data (Strings, Interger, etc.) and SelectList selections sem to need an actionfunction for the data to make it to the controller.

 

admintrmpadmintrmp
Use a commandButton to save your data. The variables within your controller get updated based on your input fields on the Visualforce page.
Cory CowgillCory Cowgill

Force.com uses traditionaly MVC. Under the covers it is actually JEE / JSF with RichFaces. Your Controller is actually a JavaBean. All the <apex:> tags are actually wrappers around JSF taglibs. If you look at the rendered HTML code and compare to JSF pages yous ee they are the same.

 

As for passing information between the layers of MVC Salesforce.com uses ViewState information in the page to maintain the state of variables between the Controller and View, just like JSF / JEE.

 

Therefore:

 

1. If you set variables in your controller to Public with get and set methods bound (ex: public Opportunity1 {get;set;}), you can bind directly to them using inputFields in your view (ex: <apex:inputField value="{!Opportunity1.CloseDate}") and they will be persisted in the ViewState.

 

2. If you use the keyword TRANSIENT on variables the value will not be persisted in the ViewState. You can use this to save room in the ViewState when you don't need to persist variables.

 

3. ActionFunction executes AJAX to pass information back and forth from the client to the server. Using ActionFunction in conjunction with ReRednering components in a VF page will process AJAX functions, updating the ViewState.

 

4. You can pass information between the view layer without persisting in the ViewState by using JavaScript Remoting.

Cory CowgillCory Cowgill

Finally if you use CommandButton and invoke an action the ViewState is of course passed along back to the Server and your method will execute with information updated in the ViewLayer.

 

Perhaps this will help:

http://wiki.developerforce.com/page/An_Introduction_to_Visualforce_View_State

This was selected as the best answer
sf_evolutionsf_evolution

Thanks for the great info Cory.

I guess what prompted the posting of my issue is that I have somewhat of a curious case, in that I'm not dealing directly with SObjects at all - I'm specifically dealing with JSON data and HTTP callbacks that are prompted from user input from apex inputtext tags, so your information about client server refresh has been very helpful.

 

A question I have is, it seems like if a value is entered in an inputtextbox, or more commonly, as user just cuts and pastes a text value into an imputtext box, and a commandbutton is pushed, the value of the inputtext box isn't  passsed to the controller unless the user specifically tabs off of the inputtext box.

 

I don't know if this is because of the way I've coded the page or something that I'm missing (a javascript event or some such).

 

admintrmpadmintrmp

Sounds like it's the way you have coded.

 

If you have coded it correctly, you should always expect your inputs to be sent to the controller and handled.

 

If I were you, I would start off with a very simple visualforce page with an input, a simple method and class property. And just pass the data between the two. You will get a feel for it then.

admintrmpadmintrmp
I would just like to point out also, that all you need is in your test visualforce is a form, command button and an input field. There is no need for any javascript, action tags, etc.
Cory CowgillCory Cowgill

I would add that if you are working with JSON data you may want to look at using Javascript Remoting.

 

Javascript Remoting does not work with the ViewState - You essentially pass the information back and forth via your own Javascript Calls and this does not update the ViewState.  You define Global Static methods with the @Remote annotation and pass along JSON and the controller will return values back to your Javascript.

 

It may be a better option for you than using ViewState:

 

Javascript Remoting:

http://www.salesforce.com/us/developer/docs/pages/Content/pages_js_remoting.htm

 

Blog Post

http://blogs.developerforce.com/developer-relations/2011/02/quick-look-into-javascript-remoting.html

 

 

admintrmpadmintrmp
Once a managed apex class has a @RemoteAction method, can it be removed from a later release?

I always thought it was a permanent method once packaged.
Pramod KumarPramod Kumar

What if page is getting refreshed on some particular selection. In that case if you will not use <apex:actionFuntion/>  your selected values will be lost.

 

 

Pramod KumarPramod Kumar

What if page is getting refreshed on some particular selection. In that case if you will not use <apex:actionFuntion/>  your selected values will be lost.

 

sf_evolutionsf_evolution

Hi Paramod,

 

This is exactly what my original post was discussing.

 

It appears that input values must make a "round trip" from VF to controller inorder to be refreshed.   My original post was regarding SelectLists, but it seems to be regarding all formos of inputs.   Checkboxes, InputText, etc.

 

I tend to program "mashups" - JSON parsing from callouts, etc. and not so much SObjects.

 

I don't know if the "round trip" is required with updating SObjects.