Persisting Values in ColdBox

I have never found a way to validate data I feel is 100% right for me, but I think I am getting close, let me explain.

I have a simple ColdBox 'view' containing my user form. This form is used to both create and update user's credentials.

   view plainprintabout
 user view
 
 <cfoutput>
  <fieldset>
  <div class="fm-req">
  <label for="firstname">First Name</label>
  <input id="firstname" name="firstname" type="text" class="text" value="#rc.bean.getfirstname()#" maxlength="15">
  </div>
  <div class="fm-req">
10   <label for="surname">Last Name</label>
11   <input id="surname" name="surname" type="text" class="text" maxlength="15" value="#rc.bean.getsurname()#">
12   </div>
13   <div class="fm-req">
14   <label for="email">Email Address</label>
15   <input id="email" name="email" type="text" class="text" maxlength="100" value="#rc.bean.getemail()#">
16   </div>
17   <div class="fm-req">
18   <label for="username">Username</label>
19   <input id="username" name="username" type="text" class="text" maxlength="12" value="#rc.bean.getusername()#">
20   </div>
21   <div class="fm-req">
22   <label for="password">Password</label>
23   <input id="password" name="password" type="password" class="text" maxlength="20" value="#variables.PasswordEncrypt#">
24   </div>
25   </fieldset>
26  </cfoutput>
   view plainprintabout
 example handler
 
 <!--- Edit User --->
 <cffunction name="editUser" access="public" returntype="void" output="false">
 <cfargument name="Event" type="coldbox.system.beans.requestContext">
  <cfscript>
      var rc = event.getCollection();// RC Reference
 
var userBean = variables.adminUsersService.createAdminUserBean(); //Create adminUserBean
 
     getPlugin('beanFactory').populateBean(userBean);//the magic bean machine
10  
     variables.adminUsersService.getUserByID(userBean);
11       rc.bean = userBean;
12       event.setValue("pageTitle","Edit System User");//Form H1 Title
13  
     event.setValue("formURL","/users/updateUser?adminId=#rc.adminId#");
14       event.setValue("buttonValue1","Update User");//H1 Title
15  
     runEvent(event='users.createUserTabs',private=true); // Create User Tabs
16  
     Event.setView("user/edit"); // Set the View To Display, after Logic
17  
</cfscript>
18  </cffunction>

I use one handler to create a new user and another to update, the only difference is the update handler pre populates the object from the database. So far simple stuff. Next I needed to validate my input. Again simple, I would submit to an intermediate handler that would validate my data against the object. However my dilemma is what to do if validation fails!

   view plainprintabout
 <!--- Validation --->
 <cffunction name="validation" access="public" returntype="void" output="false">
 <cfargument name="Event" type="coldbox.system.beans.requestContext">
  <cfscript>
      var rc = event.getCollection();// RC Reference
 
var userBean = variables.adminUsersService.createAdminUserBean(); //Create adminUserBean
 
getPlugin('beanFactory').populateBean(userBean);//the magic bean machine
 
    
      errors = userBean.validateUserALL();//Check For Validation Errors
10  
    
11       if NOTT ArrayLen(errors)){//No Validation Errors
12  
    
13           if ( variables.adminUsersService.updateUser(userBean)) {//Update Was OK
14  
             getPlugin("messagebox").setMessage("info", "User was successfully updated.");
15           }
16           else {//Could Not Update User Show Error Message
17  
             getPlugin("messagebox").setMessage("error", "Sorry, for some reason this user was not updated!");
18           }
19          
20       setNextEvent('users.overView'); // Set the Event To Run, After Logic
21  
     }//End Of No Validation Errors
22  
    
23       else {//We Have Validation Errors Show The User A Message
24  
getPlugin("messagebox").setMessage("error", "<b>The Following Validation Errors Occurred:</b><br />",errors);
25          
26   ///what to do here?
27  
        
28   }
29  
</cfscript>
30  </cffunction>

Option 1: Do I include the 'view' again within the validation handler so the object data would persist?

Option 2: Do I take them back to the original handler that made the post?

Now option 2 would mean my objects data would not persist, it would either be repopulated by the update handler or cleared by the create handler!

However I favour option 2 because by going back to the original handler you don't see in the URL the name of the validation handler as it only an intermediate stage.

So how do you persist the entire object so the user does not lose the data they have posted?

Well ColdBox has an internal flash memory that you can use in order to persist variables across requests without sending them via the URL. – direct quote. I could do the following I guess...

   view plainprintabout
 else {//We Have Validation Errors Show The User A Message
 getPlugin("messagebox").setMessage("error", "<b>The Following Validation Errors Occurred:</b><br />",errors);
 myStruct = {FIRSTNAME=userBean.getFIRSTNAME()}; //etc.....
 persistVariables(varStruct=myStruct);
 setNextEvent(event='users.newUser');


However this gets cumbersome and I have to add variable or create a strut.

So Far I have not found a method which is easier have you?

TweetBacks
Comments
Aaron Greenlee's Gravatar One may also persist in this way:

setNextEvent

event="myEvent",persist="list,of,variables,in,request,collection
# Posted By Aaron Greenlee | 19/09/09 22:59
Tony Garcia's Gravatar ColdBox 3.0 (still in beta) introduces a flash ram object for data persistence and Luis Majano has indicated that its use will be considered best practice since the persistVariables() function and the "persist" argument of setNextEvent() will be deprecated in future versions of ColdBox. See this:
http://forums.coldbox.org/index.cfm?event=ehMessag...
# Posted By Tony Garcia | 19/09/09 23:27
Glyn Jackson's Gravatar interesting post, quote...
"Why would I want to perisist the value I'm submitting with the form, you ask?"
glad its was answered and not just me! after fully testing my code I did have a few issues. version 3 looks like its going to address a lot. thanks for the post.

does anyone else do this another way, if validation fails what do you do?
# Posted By Glyn Jackson | 20/09/09 00:03
dickbob's Gravatar I'm just starting to look at Coldbox but I have many years using Fusebox. I like self-submitting forms. Your edit form submits to itself and you use the existence of form.formfields as the test to see if the page is on it's initial presentation or as the result of the submit. If it is the result of a submit you call your validation routine and then redirect to the next page if the validation is passed. If not you handled the errors on the page.
# Posted By dickbob | 21/09/09 10:07
Glyn Jackson's Gravatar @dickbob
The problem you have with that method is you would have to maintain your validation in both the update, create or anything other systems you use. where if you just had one validation handler like in my example this would not be the case. When an application gets large I really appreciate the extra work and for me its worth the effort.
# Posted By Glyn Jackson | 04/10/09 22:36
Russ Michaels's Gravatar My preferred method is to have the same page for add/edit/delete and a bit of logic that just decides what to do depending on what method your using.
If its ADD, then use blank fields, if it is edit then pre-populate, if it is delete just display non editable data.
You can then use a CFC for both cleint and server side validation, just call it via AJAX to do the client side. There is a nice cfc on riaforge that does it all for you now.
# Posted By Russ Michaels | 27/11/09 23:15
göran's Gravatar One easy way to do it is to validate in the handler that you use to save the form items. For example In my doSaveUser handler I have:

Populate Bean:
<cfset getPlugin("beanFactory").populateBean(rc.user)>
<cfset rc.user.setUserType(userType)>
<cfset rc.user.setUpdatedOn(now())>

Validate Password

<cfif newPassword neq "" and newPassword eq confirmPassword>
<cfset rc.user.setPassword(newPassword)>
<cfelseif newPassword neq "" and newPassword neq confirmPassword>
<cfset getPlugin("messagebox").setMessage("error", "Validation error: Passwords are not equal")>
<cfset isValidationError = 1>
</cfif>
      
<!--- Validation Error? --->
<cfif isValidationError>
<cfset dspEditUser(Event)>
<cfelse>
<cfset getPlugin("ioc").getBean("UserManager").saveUser(rc.user)>      
<cfset setNextEvent("admin.ehUser.dspUsers")>
</cfif>

If a validation error occurs the message plugin is run and then <cfset dspEditUser(Event)> will run the dspEditUser handler again but now populated with the form fields that are correct and the password field empty and a message box at the top.

In my dspeditUser I only have:

<cffunction name="dspEditUser" access="public" returntype="void" output="false">
      <cfargument name="Event" type="coldbox.system.beans.requestContext">
      <cfset var rc = Event.getCollection() />
      
      <cfif not isDefined("rc.user")>
         <cfset rc.user = getPlugin("ioc").getBean("UserManager").getUser( Event.getValue("userId","") ) />   
      </cfif>
      <cfset rc.userTypes = getPlugin("ioc").getBean("UserManager").getUserTypes()>
      <!--- EXIT EVENT HANDLERS: --->
      <cfset rc.xehSave = "admin.ehUser.doSaveUser">         
      <cfset rc.xehBack = "admin.ehUser.dspUsers">         

      <cfset Event.setView("user/edit")>      
</cffunction>

I use dspEditUser both for new users and to edit users. If there is no user bean in the RC a new one is created and if one exist the form field is populated from the bean. This way I only need three handlers and views for CRUD operations and does not need to persist any data. I use Transfer and LightWire to glue it togheter. I know that it´s getting way more complicated if you do for example a wizard where a user will be able to navigate back and forth or you include a JQuery/AJAX functionality in your forms. I have based my cfoo learning and developement on Ernst van der Linden´s excellent examples.
# Posted By göran | 02/12/09 03:53
 

About Me

Glyn Jackson, 27 years old, MD and senior developer of a development firm based in Staffordshire called Newebia Ltd. Academic background in BSc Information System & Internet Commerce. Online marketing expert (EE Ranked) and .NET developer. Has been developing with ColdFusion for 5 years and loves it. "I am not a veteran in ColdFusion but I do work on challenging projects which help me learn more about ColdFusion and if I can contribute to the community in anyway then, it's all good!"

Recommends

  • ColdFusion