You need to sign in to do that
Don't have an account?

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.
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
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.
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.
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.
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
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).
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.
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
I always thought it was a permanent method once packaged.
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.
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.
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.