HomeAbout Mark van HedelContact Mark van Hedel



Using FLEX for input forms in BlogCFC :: Part 1

At this moment I've started a little test project just to see how this will work. I'm making minor changes to BlogCFC to make it work with FLEX and remote objects, this to replace the addComments feature of the blog. Main reason for this is the captcha necessity. I've been working on a few private sites myself and the main problem is the automatic posting by engines of spam. One way to solve this problem is adding a captcha image to the site. Another is to make sure you don't do a post or get from a form, since that is the page that is targeted by the engines. I've already make changes to that site making the forms in FLEX and using remote objects to post the information to the page and that seems to work very well. Of course it will not remove the problem of people adding spam themselves, but that is one problem that is also not solved with adding a captcha image to the form.

So far I've started on creating a form in FLEX with the same entry fields that exist in the addComments.cfm file that is already in the current Blog.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="creationCompleteHandler()">
   <mx:Style source="css/flexform.css"/>
   <mx:Script source="actionscript/CommentsAs.as"/>
   <mx:RemoteObject id="remoteUpdate" destination="ColdFusion" source="org.flexpair.blog.RemoteUpdateConnection" showBusyCursor="true"/>
   <!-- Title -->
   <mx:ApplicationControlBar dock="true">
      <mx:Label text="{_rbValues.comments} : {_entry.title}" styleName="header" horizontalCenter="0" textAlign="center" width="100%"/>
   </mx:ApplicationControlBar>

   <mx:Panel layout="absolute" title="{_rbValues.postyourcomments}">
      <mx:Form width="100%" height="100%">
         <mx:FormItem label="{_rbValues.name} :">
            <mx:TextInput width="300" maxChars="50" id="commenterName"/>
         </mx:FormItem>
         <mx:FormItem label="{_rbValues.emailaddress} :">
            <mx:TextInput width="300" maxChars="50" id="email"/>
         </mx:FormItem>
         <mx:FormItem label="{_rbValues.website} :">
            <mx:TextInput text="http://" width="300" maxChars="255" id="website"/>
         </mx:FormItem>
         <mx:FormItem label="{_rbValues.comments} :">
            <mx:TextArea width="300" height="150" id="comments"/>
         </mx:FormItem>
         <mx:FormItem label="{_rbValues.remembermyinfo}">
            <mx:CheckBox id="remember"/>
         </mx:FormItem>
         <mx:FormItem label="{_rbValues.subscribe}">
            <mx:CheckBox id="subscribe"/>
         </mx:FormItem>
         <mx:Label text="{_rbValues.subscribetext}"/>
         <mx:FormItem>
            <mx:HBox width="100%">
               <mx:Button label="{_rbValues.cancel}" id="cancel" click="cancelFormHandler()"/>
               <mx:Button label="{_rbValues.post}" id="post" click="submitFormHandler(event)"/>
            </mx:HBox>
         </mx:FormItem>
      </mx:Form>
   </mx:Panel>
</mx:Application>

Second I started working on the multilingual part of the form and added the resource bundle values. I've done this by creating a Value Object with in there all values needed for this form. This was mostly done so I don't have to make a call for every string I output. There are lot's of ways of doing this, but I've chosen to use a Remote Object connection for this. So for that I created a ColdFusion CFC and in there receive a string with what form info I want and return a structure back to FLEX.

<cffunction name="retrieveRbValues" displayname="retrieveRbValues" hint="Retrieve resource bundle values" access="remote" output="false" returntype="struct">
      <cfargument name="page" type="string" required="true" displayname="page">
      <cfscript>
         // Create a new struct to add all values
         var rbValues = structNew();
         rb = application.utils.getResource;
         if (arguments.page == "addComments"){
            rbValues.mustincludename = rb("mustincludename");
            rbValues.mustincludeemail = rb("mustincludeemail");
            rbValues.invalidurl = rb("invalidurl");
            rbValues.mustincludecomments = rb("mustincludecomments");
            rbValues.comments = rb("comments");
         rbValues.postyourcomments = rb("postyourcomments");
            rbValues.name = rb("name");
            rbValues.emailaddress = rb("emailaddress");
            rbValues.website = rb("website");
            rbValues.remembermyinfo = rb("remembermyinfo");
            rbValues.subscribe = rb("subscribe");
            rbValues.subscribetext = rb("subscribetext");
            rbValues.cancel = rb("cancel");
            rbValues.cancelconfirm = rb("cancelconfirm");
            rbValues.post = rb("post");
            rbValues.commentsnotallowed = rb("commentsnotallowed");
         }
         return rbValues;
      </cfscript>
   </cffunction>

The value object looks like this :

package org.flexpair.blog.vo
{
   [Bindable]
   public class ResourceBundleVo
   {
      public var mustincludename:String = "";
      public var mustincludeemail:String = "";
      public var invalidurl:String = "";
      public var mustincludecomments:String = "";
      public var comments:String = "";
      public var postyourcomments:String = "";
      public var name:String = "";
      public var emailaddress:String = "";
      public var website:String = "";
      public var remembermyinfo:String = "";
      public var subscribe:String = "";
      public var subscribetext:String = "";
      public var cancel:String = "";
      public var cancelconfirm:String = "";
      public var post:String = "";
      public var commentsnotallowed:String = "";
      
   }
}

After that I've created the call on creationComplete to retrieve the information. and created a responder to answer the reply to the call, in this case the responder will fill the Value Object with values so it will directly be displayed in the form.

/**
* Handle creation complete event to retrieve data and populate the form.
*/
private function creationCompleteHandler():void {
   _responder = new ResourceBundleResponder();
   _responder.rbValues = _rbValues;
   var token:AsyncToken = remoteUpdate.retrieveRbValues("addComments");
   token.addResponder(_responder);
}

responder :

package org.flexpair.blog.responders
{
   import mx.controls.Alert;
   import mx.rpc.IResponder;
   import mx.rpc.events.FaultEvent;
   import mx.rpc.events.ResultEvent;

   import org.flexpair.blog.vo.ResourceBundleVo;

   public class ResourceBundleResponder implements IResponder
   {
      [Bindable]
      public var rbValues:ResourceBundleVo;
      /**
       * Handle the result of retrieving resource bundle data from the server
       */
      public function result(data:Object):void
      {
         // Fill the object with values
         var re:ResultEvent = data as ResultEvent;
         rbValues.name = re.result.NAME;
         rbValues.mustincludename = re.result.MUSTINCLUDENAME;
         rbValues.mustincludeemail = re.result.MUSTINCLUDEEMAIL;
         rbValues.invalidurl = re.result.INVALIDURL;
         rbValues.mustincludecomments = re.result.MUSTINCLUDECOMMENTS;
         rbValues.comments = re.result.COMMENTS;
         rbValues.postyourcomments = re.result.POSTYOURCOMMENTS;
         rbValues.emailaddress = re.result.EMAILADDRESS;
         rbValues.website = re.result.WEBSITE;
         rbValues.remembermyinfo = re.result.REMEMBERMYINFO;
         rbValues.subscribe = re.result.SUBSCRIBE;
         rbValues.subscribetext = re.result.SUBSCRIBETEXT;
         rbValues.cancel = re.result.CANCEL;
         rbValues.cancelconfirm = re.result.CANCELCONFIRM;
         rbValues.post = re.result.POST;
         rbValues.commentsnotallowed = re.result.COMMENTSNOTALLOWED;
      }

      /**
       * Handle any fault in the retrieval of resource bundle data
       */
      public function fault(info:Object):void
      {
         //TODO: implement function
         var fault:FaultEvent = info as FaultEvent;
         Alert.show(fault.message.toString());
      }
      
   }
}

So far this is working, I'll continue my little project probably somewhere later this week and keep updates posted here, I'll make sure the result at the end is also posted here for download.

Comments
mark's Gravatar It seems like the new comments form is working, I've just added it to the application and will with the rest of these blog entries explain how it was done and give you the code for download when I'm completely satisfied with the result.
# Posted By mark | 4/1/08 4:05 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.002. Contact Blog Owner