After a week of being sick I am finally getting back on track with my blogging. This is going to be one of the final entries in my Building an Application with ColdBox series. There are a lot of other things I want to blog about. I will still blog on ColdBox topics, just separate from this series.
Last time we talked about how to go about validation. Validation is a really complicated subject that I am still struggling with. I understand the concepts of the different ways of doing it, I just cannot seem to make the time to figure out how I want to do it. I think I will be looking at ValidateThis! in the near future.
In the meantime, we are going to do some pretty rudimentary validation to keep this project moving. I have decided to create a bean that can validate its own data, but then to continue using the BeanFactory plugin to populate the bean. This is not the best way to do this, in my opinion, but it is A way to do it. The main thing I want to show here is how to use the MessageBox plugin and how to persist data from one event handler to another.
So first we are going to modify the validate() method in our List.cfc.
<cffunction name="validate" access="public" returntype="array" output="false">
<cfargument name="formData" type="struct" required="true" />
<cfset var errors = arrayNew(1) />
<!--- name --->
<cfif NOT StructKeyExists(formData,"name") OR NOT Len(formData.name)>
<cfset ArrayAppend(errors, "You must enter a name") />
<!--- priority --->
<cfif NOT StructKeyExists(formData,"priority") OR NOT ListFind("1,2,3",formData.priority)>
<cfset ArrayAppend(errors, "You must choose a priority") />
<cfreturn errors />
Here we are accepting the form data submitted by the user as a struct and returning an array of error messages. Again, this is very simple data validation and you will want to look at other ways to handle this and use the way that is best for you. I am looking at ways of using a validation object so that my business objects are not determining the application's validation requirements, as is the case here.
Next, we are going to modify our event handler to call this validation method and pass in the form data.
<cffunction name="doAddList" access="public" returntype="void" output="false">
<cfargument name="Event" required="true" type="coldbox.system.beans.requestcontext" />
<cfset var rc = event.getCollection()>
<cfset var listBean = variables.todoService.newList() />
<cfset var errors = listBean.validate(rc) />
<cfif NOT ArrayLen(errors)>
<cfset getPlugin('beanFactory').populateBean(listBean) />
<cfset variables.todoService.saveList(listBean) />
<cfset getPlugin("messagebox").setMessage("info", "List Saved")>
<cfset setNextEvent('list.allLists') />
<cfset getPlugin("messagebox").setMessage("error", "Errors:<br />", errors) />
<cfset setNextEvent('list.addList',"",false,"name,priority") />
Here we have added a few things. We've added a local error array that we assign the results of our validate() method that we just created in our list bean.
Next we see if there are any error messages in there. If there are no errors, then we populate the bean and save it, as we did before, but then we are adding a message to the MessageBox plugin before we pass it on to the next event, list.allLists. We'll look at how to render the message in a moment.
The setMessage() method of the MessageBox plugin takes three arguments.
- The first argument tells ColdBox what kind of message to render. The choices are "info", "error" and "warning"
- The second argument is a string for a single error message
- The third argument is for an array of error messages if you have more than one to display.
If there are error messages then we use the MessageBox plugin to set the array of errors messages and then we direct the user back to the addList event.
Notice the additional parameters in the setNextEvent() method. Here, we are telling setNextEvent() to set 'list.addList' as the next event, not to pass any additional URL parameters, not to add the URL token, and then the last parameter is to tell the controller to persist the listed values from the RequestContext(Event) to the next event, because we want them to be pre-filled in the listForm when we return the user to the form.
Next we need to add the code to render messages from the MessageBox plugin, if any exist:
Paste this code at the top of the listForm.cfm and allLists.cfm views. If there is a message box, it will render it, if not, then nothing will show up. The "true" parameter being passed into the renderit() method tells the MessageBox plugin to clear the messages so they don't show up again.
In my next post, I will probably wrap this series up and attach the finished application. Anything new I add will probably be a review of something we have already done, so there is not much point in doing step-by-step any further. If I do come across something that we have not discussed, I will add it to the final post.