{"id":1296,"date":"2011-02-07T10:35:12","date_gmt":"2011-02-07T15:35:12","guid":{"rendered":"http:\/\/www.lonhosford.com\/lonblog\/?p=1296"},"modified":"2015-07-31T18:25:50","modified_gmt":"2015-07-31T23:25:50","slug":"basic-parsley-mvc-flash-builder-actionscript-project","status":"publish","type":"post","link":"https:\/\/www.lonhosford.com\/lonblog\/2011\/02\/07\/basic-parsley-mvc-flash-builder-actionscript-project\/","title":{"rendered":"Basic Parsley MVC Flash Builder Actionscript Project"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p><script src=\"https:\/\/connect.facebook.net\/en_US\/all.js#appId=105467682877384&amp;xfbml=1\"><\/script><fb:like href=\"https:\/\/www.lonhosford.com\/lonblog\/2011\/02\/07\/basic-parsley-mvc-flash-builder-actionscript-project\/\" send=\"true\" width=\"450\" show_faces=\"true\" font=\"\"><\/fb:like><\/p>\n<p>This is a basic model view controller example of a <a href=\"http:\/\/www.spicefactory.org\/parsley\/\" target = \"_blank\">Parsley<\/a> Actionscript project created in Flash Builder. I posted in this blog a minimalist example of using Parsley without implementing model view controller. See <a href=\"https:\/\/www.lonhosford.com\/lonblog\/2011\/01\/26\/parsley-hello-world-for-a-flash-builder-actionscript-project\/\">Parsley Hello World For A Flash Builder Actionscript Project.<\/a>. <img loading=\"lazy\" decoding=\"async\" alt=\"\" src=\"http:\/\/lh6.ggpht.com\/_e5pwU0LJbN8\/TUDbXBX15QI\/AAAAAAAAFyI\/yx_5bTk9wBc\/s800\/ParselyHelloWorld_AS_published.png\" class=\"alignleft\" width=\"370\" height=\"201\" \/>In that post I explained the messaging in Parsley and will not repeat that explanation in this post other than to point them out where used in the model view controller implementation.<\/p>\n<p>This model view controller example is as basic as I can make it while best trying to show the decoupling magic in Parsley. This is accomplished using the Parsley messaging and injection. I attempted to keep the view decoupled from the controller and model. The model and the controller could be decoupled from each other. How far you go with this depends on how many messages you want to design. To keep simple I did have the controller include the model and directly call model methods. This could be decoupled with a Parsley message.<\/p>\n<p>This example follows a few techniques in a referenced example found in the <a href=\"http:\/\/spicefactory.org\/parsley\/documentation.php\" target = \"_blank\">Spicefactory Parsley Developer Manual<\/a> in chapter 1 under &#8220;Other Resources&#8221;. This example is found at <a href=\"http:\/\/www.sitronnier.com\/blog\/parsley-2-basic-flash-example\" target = \"_blank\">BloggingLemon<\/a>. It was written in July 2009.  There is a live demo and you can view the source code. Unfortunately the article has no explanations. It did provide me a good template for the Parsley bootstrapping. I tried to streamline that example even further and document what I know here.<\/p>\n<p>You can build this with the free Flex SDK by using the code in the src folder and be sure to include a path to the Parsley and Spicelib library. I have included the Flash Builder 4 project file here you can download.<\/p>\n<ul style = \"padding-top:10px\">\n<li><a href=\"https:\/\/www.lonhosford.com\/content\/flex\/Parsley\/ParsleyFramework_MVC_AS.zip\"  onClick=\"javascript: pageTracker._trackPageview('\/downloads\/Parsley\/ParsleyFramework_MVC_AS.zip'); \">Flex Builder 4 Actionscript Project<\/a><\/li>\n<\/ul>\n<p>[ad name=&#8221;Google Adsense&#8221;]<br \/>\n<strong>Application Class &#8211; ParsleyFramework_MVC_AS.as<\/strong><\/p>\n<p>This is the bootstrap application class. One of the issues in Flash using the XML Parsley configuration file are classes not tied to the view. These classes need to be compiled early so that Parsley can reflect on them. In our case the ApplicationModel and ApplicationController classes fall into this category. There are three techniques to include them for Parsley and I repeated the Parsley Developer&#8217;s Manual notes in the comments on line 35 &#8211; 39. I borrowed the first technique also used in the <a href=\"http:\/\/www.sitronnier.com\/blog\/parsley-2-basic-flash-example\" target = \"_blank\">BloggingLemon<\/a> example which is considered by some a hack. Line 41 shows including these classes in an array that has no other use in this class and seems simple enough but should be clearly documented so they are not removed as orphaned code. <\/p>\n<p>Lines 53 &#8211; 60 configure the Parsley log messaging useful for debugging Parsley. Here we are suppressing the Parsley messaging so you can view the trace statements I added to help follow the application model view controller and Parsely messaging. <\/p>\n<p>Lines 89 and 90 of the initApp method load the Parsley xml configuration file shown later in this post.<\/p>\n<p>Lines 100 and 103 of the contextEventInitializedHandler method create Parsley managed objects for the two views in this application. The input view allows you to enter and send a message. The output view is a Flash TextField that shows all the messages in reverse entry order. Actually the ApplicationModel maintains the reverse order and the view only displays the model.<\/p>\n<p>The trace statements will show you the flow of the class as it bootstraps.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage\r\n{\r\n\timport controllers.ApplicationController;\r\n\t\r\n\timport flash.display.Sprite;\r\n\timport flash.display.StageAlign;\r\n\timport flash.display.StageScaleMode;\r\n\timport flash.events.Event;\r\n\t\r\n\timport models.ApplicationModel;\r\n\t\r\n\timport org.spicefactory.lib.flash.logging.Appender;\r\n\timport org.spicefactory.lib.flash.logging.FlashLogFactory;\r\n\timport org.spicefactory.lib.flash.logging.LogLevel;\r\n\timport org.spicefactory.lib.flash.logging.impl.DefaultLogFactory;\r\n\timport org.spicefactory.lib.flash.logging.impl.TraceAppender;\r\n\timport org.spicefactory.lib.logging.LogContext;\r\n\timport org.spicefactory.lib.logging.Logger;\r\n\timport org.spicefactory.parsley.core.context.Context;\r\n\timport org.spicefactory.parsley.core.events.ContextEvent;\r\n\timport org.spicefactory.parsley.flash.logging.FlashLoggingXmlSupport;\r\n\timport org.spicefactory.parsley.xml.XmlContextBuilder;\r\n\t\r\n\timport views.InputView;\r\n\timport views.OutputView;\r\n\r\n\t&#x5B;SWF(frameRate=&quot;30&quot;, width=&quot;800&quot;, height=&quot;650&quot;, backgroundColor=&quot;0x666666&quot;)]\t\r\n\t\r\n\tpublic class ParsleyFramework_MVC_AS extends Sprite\r\n\t{\r\n\t\t\/**\r\n\t\t * Hack to force compiling of classes configured in ParsleyConfiguration.xml \r\n\t\t * not used in this class so Parsley can reflect on them. \r\n\t\t * \r\n\t\t * Alternatives to this hack include either \r\n\t\t * compiling them into an SWC (with compc you can include \r\n\t\t * whole source folders into the SWC) and then include the whole SWC into your SWF \r\n\t\t * with the -include-libraries option of the mxmlc compiler.\r\n\t\t * or include individual classes with the -includes option of the mxmlc compiler. \r\n\t\t * *\/\r\n\t\tprotected var classImporter:Array = &#x5B;ApplicationModel, ApplicationController];\r\n\t\t\/**\r\n\t\t * This app's context for Parsley.\r\n\t\t * *\/\r\n\t\tprotected var mainContext:Context;\r\n\t\t\/**\r\n\t\t * Application bootstrap class.\r\n\t\t * *\/\r\n\t\tpublic function ParsleyFramework_MVC_AS()\r\n\t\t{\r\n\t\t\tsuper();\r\n\t\t\ttrace(&quot;INIT: ParsleyFramework_MVC_AS()&quot;);\r\n\t\t\tvar factory:FlashLogFactory = new DefaultLogFactory();\r\n\t\t\t\/\/ Spicefactory warning level for logging.\r\n\t\t\tfactory.setRootLogLevel(LogLevel.WARN);\r\n\t\t\tvar traceApp:Appender = new TraceAppender();\r\n\t\t\t\/\/ Suppress SpiceFactory lib tracing.\r\n\t\t\ttraceApp.threshold = LogLevel.OFF;\r\n\t\t\tfactory.addAppender(traceApp);\r\n\t\t\tLogContext.factory = factory;\r\n\t\t\tif (stage == null) \r\n\t\t\t{\r\n\t\t\t\taddEventListener(Event.ADDED_TO_STAGE, addedToStageEventHandler);\r\n\t\t\t}\r\n\t\t\telse \r\n\t\t\t{\r\n\t\t\t\tinitApp();\r\n\t\t\t}\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handler for ADDED_TO_STAGE EVENT\r\n\t\t *\/\r\n\t\tprotected function addedToStageEventHandler(event:Event):void\r\n\t\t{\r\n\t\t\ttrace(&quot;INIT: ParsleyFramework_MVC_AS.addedToStageEventHandler(...)&quot;);\r\n\t\t\tremoveEventListener(Event.ADDED_TO_STAGE, addedToStageEventHandler);\r\n\t\t\tinitApp();\r\n\t\t} \r\n\t\t\/**\r\n\t\t * Initialize the stage and load Parsley configuration.\r\n\t\t *\/\r\n\t\tprotected function initApp():void\r\n\t\t{            \r\n\t\t\ttrace(&quot;INIT: ParsleyFramework_MVC_AS.initApp()&quot;);\r\n\t\t\tstage.align = StageAlign.TOP_LEFT;\r\n\t\t\tstage.scaleMode = StageScaleMode.NO_SCALE;\r\n\t\t\tFlashLoggingXmlSupport.initialize();\r\n\t\t\t\/\/ INITIALIZE CONTEXT\r\n\t\t\tmainContext = XmlContextBuilder.build(&quot;ParsleyConfiguration.xml&quot;);\r\n\t\t\tmainContext.addEventListener(ContextEvent.INITIALIZED, contextEventInitializedHandler); \r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handler for Parsley ContextEvent.INITIALIZED event.\r\n\t\t *\/\r\n\t\tprotected function contextEventInitializedHandler(event:ContextEvent):void\r\n\t\t{    \r\n\t\t\ttrace(&quot;INIT: ParsleyFramework_MVC_AS.contextEventInitializedHandler(...)&quot;);\r\n\t\t\tmainContext.removeEventListener(ContextEvent.INITIALIZED, contextEventInitializedHandler);\r\n\t\t\t\/\/ Add in the views.\r\n\t\t\tvar inputView:InputView = mainContext.getObjectByType(InputView) as InputView;\r\n\t\t\taddChild(inputView);  \r\n\t\t\tinputView.y = 50;\r\n\t\t\tvar outputView:OutputView = mainContext.getObjectByType(OutputView) as OutputView;\r\n\t\t\taddChild(outputView);  \r\n\t\t\toutputView.y = inputView.y + inputView.height + 5;\r\n\t\t}        \r\n\t}\r\n}\r\n<\/pre>\n<p><strong>Parsley Configuration XML File \u2013 ParsleyConfiguration.xml<\/strong><br \/>\nFor Parsley to look for the Parsley metatags and other management tasks, it needs to know which classes to search. Loading an XML configuration file is how that is done. Here you see the model, controller and two views referenced by their package identification.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;\r\n&lt;objects \r\n    xmlns=&quot;http:\/\/www.spicefactory.org\/parsley&quot;\r\n    xmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot;\r\n    xsi:schemaLocation=&quot;http:\/\/www.spicefactory.org\/parsley \r\n        http:\/\/www.spicefactory.org\/parsley\/schema\/2.3\/parsley-core.xsd&quot;\r\n    &gt;\r\n     &lt;!-- Objects managed by Parsley --&gt;\r\n \t&lt;object type=&quot;models.ApplicationModel&quot; \/&gt;\r\n \t&lt;object type=&quot;controllers.ApplicationController&quot; \/&gt;\r\n     \r\n\t&lt;object type=&quot;views.InputView&quot; \/&gt;\r\n\t&lt;object type=&quot;views.OutputView&quot;  \/&gt; \r\n&lt;\/objects&gt;\r\n<\/pre>\n<p>[ad name=&#8221;Google Adsense&#8221;]<br \/>\n<strong>The Input View \u2013 InputView.as<\/strong><br \/>\nThis is an input TextField and an extended SimpleButton to take any typed message and send a Parsley message.<\/p>\n<p>Line 102 is where a message is dispatched for Parsley to broadcast. Lines 37 and 38 show the Parsley injection for the messaging method.<\/p>\n<p>There is no reference to a controller or a model in this view. The message on line 102 is dispatched for the chosen controller to handle. That choice is made in the controller.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage views\r\n{\r\n\timport events.SendTextMessageEvent;\r\n\timport flash.display.Sprite;\r\n\timport flash.events.Event;\r\n\timport flash.events.MouseEvent;\r\n\timport flash.text.TextField;\r\n\timport flash.text.TextFieldType;\r\n\timport flash.text.TextFormat;\r\n\timport flashx.textLayout.formats.TextAlign;\r\n\timport ui.simple.QuickButton;\r\n\t\/**\r\n\t * Demonstrates UI components sending messages confined to this view while\r\n\t * using Parsley to send the SendTextMessageEvent outside for a controller to handle.\r\n\t * *\/\r\n\tpublic class InputView extends Sprite\r\n\t{\r\n\t\t\/**\r\n\t\t * Output TextField component.\r\n\t\t * *\/\r\n\t\tprivate var input_tf:TextField;\r\n\t\t\/**\r\n\t\t * TextFormat for input_tf.\r\n\t\t * *\/\r\n\t\tprivate var tfFormat:TextFormat;\r\n\t\t\/**\r\n\t\t * The send button\r\n\t\t * *\/\r\n\t\tprivate var sendButton:QuickButton;\r\n\t\t\/**\r\n\t\t * The off button\r\n\t\t * *\/\r\n\t\tprivate var offButton:QuickButton;\r\n\t\t\/**\r\n\t\t * Parsley injected message dispatcher\r\n\t\t * *\/\r\n\t\t&#x5B;MessageDispatcher]\r\n\t\tpublic var dispatcher:Function;\r\n\t\t\/**\r\n\t\t * Constructor\r\n\t\t * *\/\r\n\t\tpublic function InputView()\r\n\t\t{\r\n\t\t\ttrace(&quot;VIEW: InputView()&quot;);\r\n\t\t\tsuper();\r\n\t\t\tcreateChildren();\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Parsley calls automatically after context parsing.\r\n\t\t *\/\r\n\t\t&#x5B;Init]\r\n\t\tpublic function parsleyInit():void\r\n\t\t{\r\n\t\t\ttrace(&quot;VIEW: InputView.parsleyInit()&quot;);\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Build the UI for this display object.\r\n\t\t *\/\r\n\t\tpublic function createChildren():void\r\n\t\t{\r\n\t\t\ttrace(&quot;VIEW: InputView.createChildren()&quot;);\r\n\t\t\t\/\/ TextFormat\r\n\t\t\ttfFormat = new TextFormat();\r\n\t\t\ttfFormat.align = TextAlign.LEFT;\r\n\t\t\ttfFormat.bold = true;\r\n\t\t\ttfFormat.font = &quot;_typewriter&quot;;\r\n\t\t\t\/\/ Input TextField.\r\n\t\t\tinput_tf = new TextField();\r\n\t\t\tinput_tf.border = true; \r\n\t\t\tinput_tf.multiline = false;\r\n\t\t\tinput_tf.type = TextFieldType.INPUT;\r\n\t\t\tinput_tf.background = true;\r\n\t\t\tinput_tf.width = 600;\r\n\t\t\tinput_tf.height = 20;\r\n\t\t\tinput_tf.addEventListener(Event.CHANGE, input_tf_changeHandler);\r\n\t\t\taddChild(input_tf);\t\r\n\t\t\t\/\/ Create QuickButton and add to display list.\r\n\t\t\tsendButton = new QuickButton(&quot;Send&quot;,60);\r\n\t\t\tsendButton.addEventListener(MouseEvent.CLICK, sendButtonClickHandler);\r\n\t\t\taddChild(sendButton);\t\r\n\t\t\tinput_tf.width -= sendButton.width + 10;\r\n\t\t\tsendButton.x = input_tf.x + input_tf.width + 10;\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handler for input_tf_changeHandler Event.CHANGE. To maintain format while changing input\r\n\t\t * text.\r\n\t\t * *\/\r\n\t\tprivate function input_tf_changeHandler(e:Event):void\r\n\t\t{\r\n\t\t\t\/\/trace(&quot;VIEW: InputView.input_tf_changeHandler(...)&quot;);\r\n\t\t\tinput_tf.setTextFormat(tfFormat);\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handler for sendButton MouseEvent.CLICK\r\n\t\t * *\/\r\n\t\tprivate function sendButtonClickHandler(e:MouseEvent):void\r\n\t\t{\r\n\t\t\ttrace(&quot;VIEW: InputView.sendButtonClickHandler(...)&quot;);\r\n\t\t\t\/\/ There is text to send\r\n\t\t\tif (input_tf.length &gt; 0)\r\n\t\t\t{\r\n\t\t\t\tdispatcher( new SendTextMessageEvent(SendTextMessageEvent.SEND, input_tf.text) );\r\n\t\t\t\tinput_tf.text = &quot;&quot;;\r\n\t\t\t\tstage.focus = input_tf;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>The Output View \u2013 OutputView.as<\/strong><\/p>\n<p>As in the InputView there is no reference to a controller or a model. Line 68 shows using Parsley to pick up a message. Of course in a model-view-controller implementation the model should dispatch this message when the model updates.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage views\r\n{\r\n\timport events.SendTextMessageEvent;\r\n\timport events.SentTextMessagesUpdateEvent;\r\n\t\r\n\timport flash.display.Sprite;\r\n\timport flash.events.MouseEvent;\r\n\timport flash.text.TextField;\r\n\timport flash.text.TextFieldType;\r\n\timport flash.text.TextFormat;\r\n\t\r\n\timport flashx.textLayout.formats.TextAlign;\r\n\r\n\t\/**\r\n\t * Simple output view. Demonstrates receiving Parsley managed messages and updating from model changes.\r\n\t * *\/\r\n\tpublic class OutputView extends Sprite\r\n\t{\r\n\t\t\/**\r\n\t\t * Output TextField component.\r\n\t\t * *\/\r\n\t\tprivate var output_tf:TextField;\r\n\t\t\/**\r\n\t\t * TextFormat for output_tf.\r\n\t\t * *\/\r\n\t\tprivate var tfFormat:TextFormat;\r\n\t\t\/**\r\n\t\t * Constructor\r\n\t\t * *\/\r\n\t\tpublic function OutputView()\r\n\t\t{\r\n\t\t\ttrace(&quot;VIEW: OutputView()&quot;);\r\n\t\t\tsuper();\r\n\t\t\tcreateChildren();\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Parsley calls automatically after context parsing.\r\n\t\t *\/\r\n\t\t&#x5B;Init]\r\n\t\tpublic function parsleyInit():void\r\n\t\t{\r\n\t\t\ttrace(&quot;VIEW: OutputView.parsleyInit()&quot;);\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Build the UI for this display object.\r\n\t\t *\/\r\n\t\tpublic function createChildren():void\r\n\t\t{\r\n\t\t\ttrace(&quot;VIEW: OutputView.createChildren()&quot;);\r\n\t\t\t\/\/ TextFormat\r\n\t\t\ttfFormat = new TextFormat();\r\n\t\t\ttfFormat.align = TextAlign.LEFT;\r\n\t\t\ttfFormat.bold = true;\r\n\t\t\ttfFormat.font = &quot;_typewriter&quot;;\r\n\t\t\t\/\/ TextField.\r\n\t\t\toutput_tf = new TextField();\r\n\t\t\toutput_tf.border = true; \r\n\t\t\toutput_tf.multiline = true;\r\n\t\t\toutput_tf.background = true;\r\n\t\t\toutput_tf.width = 600;\r\n\t\t\toutput_tf.height = 100;\r\n\t\t\taddChild(output_tf);\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Parsley event handler. Listening for SentTextMessagesUpdateEvent.UPDATE type. Shows using a selector.\r\n\t\t * Other Parsley managed views can do the same.\r\n\t\t *\/\r\n\t\t&#x5B;MessageHandler(selector=&quot;event.SentTextMessagesUpdateEvent.UPDATED&quot;)]\r\n\t\tpublic function sentTextMessagesUpdateEventHandler(event:SentTextMessagesUpdateEvent):void\r\n\t\t{\r\n\t\t\ttrace(&quot;VIEW: OutputView.sentTextMessagesUpdateEventHandler(...) - event.type: &quot; + event.type);\r\n\t\t\toutput_tf.text = event.sentTextMessages;\r\n\t\t\toutput_tf.setTextFormat(tfFormat);\r\n\t\t} \r\n\t}\r\n}\r\n<\/pre>\n<p><strong>The Model \u2013 ApplicationModel.as<\/strong><\/p>\n<p>On line 12 of the model the one data element, sentTextMessages, holds all the text messages sent in the application. The addSentTextMessage method is where the model is updated with new text messages and where sentTextMessages is maintained. The text messages in sentTextMessages are kept in &#8220;last in&#8221; order.<\/p>\n<p>Line 30 notifies the Parsley framework of changes in sentTextMessages. The wiring we applied in the Parsley framework incudes the views and the views have handlers to receive the message. In our case it is the OutputView which simply displays the sentTextMessages value as is.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage models\r\n{\r\n\timport events.SentTextMessagesUpdateEvent;\r\n\t\/**\r\n\t * The model responsible for application data.\r\n\t * *\/\r\n\tpublic class ApplicationModel\r\n\t{\r\n\t\t\/**\r\n\t\t * All text messages sent separated by new line \\n.\r\n\t\t * *\/\r\n\t\tprivate var sentTextMessages:String = &quot;&quot;;\r\n\t\t\/**\r\n\t\t * Parsley injected message dispatcher\r\n\t\t * *\/\r\n\t\t&#x5B;MessageDispatcher]\r\n\t\tpublic var dispatcher:Function;\r\n\t\t\/**\r\n\t\t * Updates the sentTextMessages property and broadcasts SentTextMessagesUpdateEvent.\r\n\t\t * @param messageText A text message sent.\r\n\t\t * *\/\r\n\t\tpublic function addSentTextMessage(messageText:String):void\r\n\t\t{\r\n\t\t\ttrace(&quot;MODEL: ApplicationModel.addSentTextMessage(...)&quot;);\r\n\t\t\tif (sentTextMessages.length &gt; 0)\r\n\t\t\t{\r\n\t\t\t\tmessageText += &quot;\\n&quot;;\r\n\t\t\t}\r\n\t\t\tsentTextMessages = messageText + sentTextMessages;\r\n\t\t\tdispatcher( new SentTextMessagesUpdateEvent(SentTextMessagesUpdateEvent.UPDATED, sentTextMessages) );\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p>[ad name=&#8221;Google Adsense&#8221;]<br \/>\n<strong>The Controller\u2013 ApplicationController.as<\/strong><\/p>\n<p>Lines 34 and 35 uses the Parsley messaging to listen for view messages and in this case the event.SendTextMessageEvent.SEND message. Views do not need to couple to this controller. Neither does the controller need to know anything about the views.<\/p>\n<p>Line 38 shows the updating of the model. However you could replace this with Parsley messaging to decouple the controller from the model. I did not in order to reduce the number of messages for the example. <\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage controllers\r\n{\r\n\timport events.SendTextMessageEvent;\r\n\t\r\n\timport models.ApplicationModel;\r\n\r\n\t\/**\r\n\t * The controller responsible for application level control.\r\n\t * *\/\r\n\tpublic class ApplicationController\r\n\t{\r\n\t\t\/**\r\n\t\t * The model injected by Parsley.\r\n\t\t * *\/\r\n\t\t&#x5B;Inject]\r\n\t\tpublic var model:ApplicationModel;\r\n\t\t\/**\r\n\t\t * Parsley injected message dispatcher\r\n\t\t * *\/\r\n\t\t&#x5B;MessageDispatcher]\r\n\t\tpublic var dispatcher:Function;\r\n\t\t\/**\r\n\t\t * Parsley calls automatically after context parsing.\r\n\t\t *\/\r\n\t\t&#x5B;Init]\r\n\t\tpublic function parsleyInit():void\r\n\t\t{\r\n\t\t\ttrace(&quot;CONTROLLER: ApplicationController.parsleyInit()&quot;);\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Parsley event handler. Listening for SendTextMessageEvent.SEND type. Shows using a selector.\r\n\t\t * Other Parsley managed views can do the same.\r\n\t\t *\/\r\n\t\t&#x5B;MessageHandler(selector=&quot;event.SendTextMessageEvent.SEND&quot;)]\r\n\t\tpublic function sendTextMessageEventHandler(event:SendTextMessageEvent):void\r\n\t\t{\r\n\t\t\ttrace(&quot;CONTROLLER: ApplicationController.sendTextMessageEventHandler(...) - event.type: &quot; + event.type);\r\n\t\t\tmodel.addSentTextMessage(event.messageText);\r\n\t\t} \r\n\t}\r\n}\r\n<\/pre>\n<p><strong>The SendTextMessageEvent\u2013 SendTextMessageEvent.as<\/strong><\/p>\n<p>This is a custom Actionscript event. The purpose is to carry a new text message.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage events\r\n{\r\n\timport flash.events.Event;\r\n\t\/**\r\n\t * Event for demonstrating Parsley. View sending a new text message.\r\n\t * *\/\r\n\tpublic class SendTextMessageEvent extends Event\r\n\t{\r\n\t\t\/**\r\n\t\t * The event send type.\r\n\t\t * *\/\r\n\t\tpublic static const SEND:String = &quot;event.SendTextMessageEvent.SEND&quot;;\r\n\t\t\/**\r\n\t\t * The text sent.\r\n\t\t * *\/\r\n\t\tpublic var messageText:String;\r\n\t\t\/**\r\n\t\t * Constructor\r\n\t\t * @param messageText The text sent.\r\n\t\t * *\/\r\n\t\tpublic function SendTextMessageEvent(type:String, messageText:String, bubbles:Boolean=false, cancelable:Boolean=false)\r\n\t\t{\r\n\t\t\tsuper(type, bubbles, cancelable);\r\n\t\t\tthis.messageText = messageText;\r\n\t\t\ttrace (&quot;EVENT: SendTextMessageEvent(...) type: &quot; + type);\r\n\t\t}\r\n\t\toverride public function clone():Event\r\n\t\t{\r\n\t\t\treturn new SendTextMessageEvent(type, messageText, bubbles, cancelable);\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>The SentTextMessagesUpdateEvent \u2013 SentTextMessagesUpdateEvent .as<\/strong><\/p>\n<p>Another custom Actionscript event. The model&#8217;s sentTextMessages property is carried in this event.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage events\r\n{\r\n\timport flash.events.Event;\r\n\t\/**\r\n\t * Event for demonstrating Parsley with mvc. Model notification of sentTextMessages updated. \r\n\t * The event does not need to be specific to the model so references to the model in\r\n\t * documentation is for helping in tracing the Parsley mvc being demonstrated.\r\n\t * *\/\r\n\tpublic class SentTextMessagesUpdateEvent extends Event\r\n\t{\r\n\t\t\/**\r\n\t\t * The event updated type.\r\n\t\t * *\/\r\n\t\tpublic static const UPDATED:String = &quot;event.SentTextMessagesUpdateEvent.UPDATED&quot;;\r\n\t\t\/**\r\n\t\t * The model value of all the sent text messages.\r\n\t\t * *\/\r\n\t\tpublic var sentTextMessages:String;\r\n\t\t\/**\r\n\t\t * Constructor\r\n\t\t * @param sentTextMessages The model's value of the sentTextMessages.\r\n\t\t * *\/\r\n\t\tpublic function SentTextMessagesUpdateEvent(type:String, sentTextMessages:String, bubbles:Boolean=false, cancelable:Boolean=false)\r\n\t\t{\r\n\t\t\tsuper(type, bubbles, cancelable);\r\n\t\t\tthis.sentTextMessages = sentTextMessages;\r\n\t\t\ttrace (&quot;EVENT: SentTextMessagesUpdateEvent(...) type: &quot; + type);\r\n\t\t}\r\n\t\toverride public function clone():Event\r\n\t\t{\r\n\t\t\treturn new SentTextMessagesUpdateEvent(type, sentTextMessages, bubbles, cancelable);\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>The QuickButton- QuickButton.as<\/strong><br \/>\nThis is just an Actionscript SimpleButton to use for the demo.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage ui.simple\r\n{\r\n\timport flash.display.DisplayObject;\r\n\timport flash.display.Shape;\r\n\timport flash.display.SimpleButton;\r\n\timport flash.events.MouseEvent;\r\n\tpublic class QuickButton extends SimpleButton\r\n\t{\r\n\t\t\/**\r\n\t\t * The up state background color;\r\n\t\t * *\/\r\n\t\tprivate var upColor:uint   = 0xFFCC00;\r\n\t\t\/**\r\n\t\t * The over state background color;\r\n\t\t * *\/\r\n\t\tprivate var overColor:uint = 0xCCFF00;\r\n\t\t\/**\r\n\t\t * The down state background color;\r\n\t\t * *\/\r\n\t\tprivate var downColor:uint = 0x00CCFF;\r\n\t\t\/**\r\n\t\t * Width.\r\n\t\t * *\/\r\n\t\tprivate var buttonWidth:Number;;\r\n\t\t\/**\r\n\t\t * Label.\r\n\t\t * *\/\r\n\t\tprivate var label:String;\r\n\t\t\/**\r\n\t\t * Constructor.\r\n\t\t * @param label The caption for button.\r\n\t\t * @param buttonWidth Width of the button. Height is 1\/3 of buttonWidth\r\n\t\t * *\/\r\n\t\tpublic function QuickButton(label:String = &quot;Button&quot;, buttonWidth:Number = 80)\r\n\t\t{\r\n\t\t\ttrace(&quot;UI: QuickButton() - label: &quot; + label);\r\n\t\t\tthis.label = label;\r\n\t\t\tthis.buttonWidth = buttonWidth;\r\n\t\t\tdownState      = new QuickButtonDisplayShape(label, downColor, buttonWidth);\r\n\t\t\toverState      = new QuickButtonDisplayShape(label, overColor, buttonWidth);\r\n\t\t\tupState        = new QuickButtonDisplayShape(label, upColor, buttonWidth);\r\n\t\t\thitTestState   = new QuickButtonDisplayShape(label, upColor, buttonWidth);\r\n\t\t\tuseHandCursor  = true;\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>The QuickButton Skin &#8211; QuickButtonDisplayShape.as<\/strong><br \/>\nHow I skinned the QuickButton.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage ui.simple\r\n{\r\n\timport flash.display.Sprite;\r\n\timport flash.text.TextField;\r\n\timport flash.text.TextFieldAutoSize;\r\n\timport flash.text.TextFormat;\r\n\timport flashx.textLayout.formats.TextAlign;\r\n\t\/**\r\n\t * Rounded button with text label. Width and height and not margins or padding.\r\n\t * *\/\r\n\tpublic class QuickButtonDisplayShape extends Sprite\r\n\t{\r\n\t\t\/**\r\n\t\t * Background color.\r\n\t\t * *\/\r\n\t\tprivate var bgColor:uint;\r\n\t\t\/**\r\n\t\t * Width.\r\n\t\t * *\/\r\n\t\tprivate var buttonWidth:Number;\r\n\t\t\/**\r\n\t\t * Height.\r\n\t\t * *\/\r\n\t\tprivate var buttonHeight:Number;\r\n\t\t\/**\r\n\t\t * Label TextField component.\r\n\t\t * *\/\r\n\t\tprivate var tf:TextField;\r\n\t\t\/**\r\n\t\t * Left padding for tf inside the button shape.\r\n\t\t * *\/\r\n\t\tprivate const TF_LEFT_PADDING:Number = 6;\r\n\t\t\/**\r\n\t\t * Right padding for tf inside the button shape.\r\n\t\t * *\/\r\n\t\tprivate const TF_RIGHT_PADDING:Number = 6;\r\n\t\t\/**\r\n\t\t * Ratio of button height to the buttonWidth.\r\n\t\t * *\/\r\n\t\tprivate const BUTTON_HEIGHT_RATIO:Number = 1\/3;\r\n\t\t\/**\r\n\t\t * Constructor.\r\n\t\t * @param label The caption for button.\r\n\t\t * @param bgColor Color for the button background.\r\n\t\t * @param buttonWidth Width of the button. Height is 1\/3 of buttonWidth\r\n\t\t * *\/\r\n\t\tpublic function QuickButtonDisplayShape(label:String,bgColor:Number, buttonWidth:Number)\r\n\t\t{\r\n\t\t\t\/\/ Consume parameters\r\n\t\t\tthis.bgColor = bgColor;\r\n\t\t\tthis.buttonWidth = buttonWidth;\r\n\t\t\tthis.buttonHeight = buttonWidth * BUTTON_HEIGHT_RATIO;\r\n\t\t\t\/\/ Draw button graphics.\r\n\t\t\tdraw();\r\n\t\t\t\/\/ TextField for the button caption.\r\n\t\t\ttf = new TextField();\r\n\t\t\tvar tfFormat:TextFormat = new TextFormat();\r\n\t\t\ttf.text = label;\r\n\t\t\t\/\/ Format for centering.\r\n\t\t\ttfFormat.align = TextAlign.CENTER;\r\n\t\t\ttfFormat.bold = true;\r\n\t\t\ttfFormat.font = &quot;_sans&quot;;\r\n\t\t\t\/\/tf.border = true; \/\/ Design guide for layout.\r\n\t\t\ttf.setTextFormat(tfFormat);\r\n\t\t\t\/\/ Position and size the caption.\r\n\t\t\ttf.x = TF_LEFT_PADDING;\r\n\t\t\ttf.width = buttonWidth - (TF_LEFT_PADDING + TF_RIGHT_PADDING);\r\n\t\t\ttf.height = tf.textHeight + 2;\r\n\t\t\ttf.y = Math.max(0, ( buttonHeight - (tf.textHeight + 4)) \/ 2);\r\n\t\t\t\/\/ Add caption.\r\n\t\t\taddChild(tf);\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Draw graphics.\r\n\t\t * *\/\r\n\t\tprivate function draw():void \r\n\t\t{\r\n\t\t\tgraphics.beginFill(bgColor);\r\n\t\t\tgraphics.drawRoundRect(0, 0, buttonWidth, buttonHeight, 20, 20);\r\n\t\t\tgraphics.endFill();\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<div id=\"fb-root\"><\/div>\n<p><script src=\"https:\/\/connect.facebook.net\/en_US\/all.js#xfbml=1\"><\/script><fb:comments href=\"https:\/\/www.lonhosford.com\/lonblog\/2011\/02\/07\/basic-parsley-mvc-flash-builder-actionscript-project\/\" num_posts=\"2\" width=\"500\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a basic model view controller example of a Parsley Actionscript project created in Flash Builder. I posted in this blog a minimalist example of using Parsley without implementing model view controller. See Parsley Hello World For A Flash Builder Actionscript Project.. In that post I explained the messaging in Parsley and will not [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[19,3,55],"class_list":["post-1296","post","type-post","status-publish","format-standard","hentry","category-general","tag-actionscript","tag-adobe-flash","tag-parsley"],"_links":{"self":[{"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/posts\/1296","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/comments?post=1296"}],"version-history":[{"count":35,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/posts\/1296\/revisions"}],"predecessor-version":[{"id":3688,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/posts\/1296\/revisions\/3688"}],"wp:attachment":[{"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/media?parent=1296"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/categories?post=1296"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/tags?post=1296"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}