| | 1 | [[TOC(heading=Training Section Contents, Training*)]] |
| | 2 | |
| | 3 | = Section 6: Flow and Dependencies = |
| | 4 | |
| | 5 | It would be nice if all application functionality was simple and we didn't have to content with real world business requirements. In this next walk-through we are going to use Model-Glue to enforce some application logic dependencies. Take special care to notice the auto-documentation features of Model-Glue when used in this way. |
| | 6 | |
| | 7 | In this next exercise, we'll be creating a form to create/update Shipment Items, and also a way to remove Shipment Items. As such, we'll need several Event Handlers, a few controllers and a new view file. |
| | 8 | |
| | 9 | 1. Open /PlantOMatic/config/ModelGlue.xml, find <event-handlers> and insert the following XML: |
| | 10 | |
| | 11 | {{{ |
| | 12 | |
| | 13 | <event-handler name="Item.Form" type="templatedPage"> |
| | 14 | <broadcasts> |
| | 15 | <message name="require"> |
| | 16 | <argument name="requiredVariable" value="ShipmentID" /> |
| | 17 | <argument name="redirectIfNotProvided" value="Shipment.List" /> |
| | 18 | </message> |
| | 19 | <message name="needPlantList" /> |
| | 20 | <message name="needItemBean" /> |
| | 21 | </broadcasts> |
| | 22 | <views> |
| | 23 | <include name="Primary" template="Form.Item.cfm"> |
| | 24 | <value name="xe_HandleSubmitForm" value="doItem.Form" /> |
| | 25 | </include> |
| | 26 | </views> |
| | 27 | </event-handler> |
| | 28 | |
| | 29 | <event-handler name="doItem.Form"> |
| | 30 | <broadcasts> |
| | 31 | <message name="handleItemBean" /> |
| | 32 | </broadcasts> |
| | 33 | <results> |
| | 34 | <result name="Failure" do="Item.Form" /> |
| | 35 | <result name="Success" do="Shipment.Display" redirect="true" append="ShipmentID" /> |
| | 36 | </results> |
| | 37 | </event-handler> |
| | 38 | |
| | 39 | <event-handler name="doItem.Remove"> |
| | 40 | <broadcasts> |
| | 41 | <message name="require"> |
| | 42 | <argument name="requiredVariable" value="ShipmentID" /> |
| | 43 | <argument name="redirectIfNotProvided" value="Shipment.List" /> |
| | 44 | </message> |
| | 45 | <message name="require"> |
| | 46 | <argument name="requiredVariable" value="ItemID" /> |
| | 47 | <argument name="redirectIfNotProvided" value="Shipment.Display" /> |
| | 48 | </message> |
| | 49 | <message name="handleItemRemove" /> |
| | 50 | </broadcasts> |
| | 51 | <results> |
| | 52 | <result name="Failure" do="Shipment.Display" /> |
| | 53 | <result name="Success" do="Shipment.Display" redirect="true" append="ShipmentID" /> |
| | 54 | </results> |
| | 55 | </event-handler> |
| | 56 | |
| | 57 | }}} |
| | 58 | |
| | 59 | 2. Open /PlantOMatic/config/ModelGlue.xml, find <controllers> and insert the following: |
| | 60 | |
| | 61 | {{{ |
| | 62 | |
| | 63 | <controller id="ItemController" type="PlantOMatic.controller.ItemController"> |
| | 64 | <message-listener message="handleItemBean" /> |
| | 65 | <message-listener message="handleItemRemove" /> |
| | 66 | <message-listener message="needItemBean" /> |
| | 67 | </controller> |
| | 68 | |
| | 69 | <controller id="PlantController" type="PlantOMatic.controller.PlantController"> |
| | 70 | <message-listener message="needPlantList" function="loadList" /> |
| | 71 | <message-listener message="needPlantSearch" function="search" /> |
| | 72 | </controller> |
| | 73 | |
| | 74 | }}} |
| | 75 | |
| | 76 | 3. Open /PlantOMatic/config/ColdSpring.xml and insert the following bean definitions for our pre-made manager objects: |
| | 77 | |
| | 78 | {{{ |
| | 79 | |
| | 80 | <bean id="ItemManager" class="PlantOMatic.model.ItemManager"> |
| | 81 | <constructor-arg name="dsn"> |
| | 82 | <bean factory-bean="reactorConfiguration" factory-method="getDsn" /> |
| | 83 | </constructor-arg> |
| | 84 | </bean> |
| | 85 | |
| | 86 | <bean id="PlantManager" class="PlantOMatic.model.PlantManager"> |
| | 87 | <constructor-arg name="dsn"> |
| | 88 | <bean factory-bean="reactorConfiguration" factory-method="getDsn" /> |
| | 89 | </constructor-arg> |
| | 90 | </bean> |
| | 91 | |
| | 92 | }}} |
| | 93 | |
| | 94 | |
| | 95 | 4. Create a file named !ItemController.cfc in the /PlantOMatic/controller directory then paste the following code in the body: |
| | 96 | |
| | 97 | {{{ |
| | 98 | |
| | 99 | <cfcomponent output="false" hint="I am a Model-Glue controller." extends="ModelGlue.gesture.controller.Controller" beans="ItemManager"> |
| | 100 | |
| | 101 | <cffunction name="handleItemBean" output="false" access="public" returntype="void"> |
| | 102 | <cfargument name="event" type="any" /> |
| | 103 | <cfset var Item = arguments.event.makeEventBean( "PlantOMatic.model.Item" ) /> |
| | 104 | <cfset var MessageContainer = arguments.event.getValue( "MessageContainer" ) /> |
| | 105 | <cfif Item.validate( MessageContainer ) IS true> |
| | 106 | <cfset beans.ItemManager.save( Item ) /> |
| | 107 | <cfset MessageContainer.addSuccess( "Your Item was saved" ) /> |
| | 108 | <cfset arguments.event.addResult( "Success" ) /> |
| | 109 | <cfelse> |
| | 110 | <cfset MessageContainer.addError( "Something bad happened" ) /> |
| | 111 | <cfset arguments.event.addResult( "Failure" ) /> |
| | 112 | </cfif> |
| | 113 | </cffunction> |
| | 114 | |
| | 115 | <cffunction name="handleItemRemove" output="false" access="public" returntype="void" hint="I deal with an Item for removal"> |
| | 116 | <cfargument name="event" type="any" /> |
| | 117 | <cfset arguments.event.getValue( "MessageContainer" ).addError( "Can not remove because we've not finished coding" ) /> |
| | 118 | <cfset arguments.event.getValue( "MessageContainer" ).addInfo( "Your homework assignment is to complete this feature" ) /> |
| | 119 | <cfset arguments.event.addResult( "Failure" ) /> |
| | 120 | </cffunction> |
| | 121 | |
| | 122 | <cffunction name="needItemBean" output="false" access="public" returntype="void" hint="I find and return information about a Item"> |
| | 123 | <cfargument name="event" type="any" /> |
| | 124 | <cfset var Item = arguments.event.makeEventBean( "PlantOMatic.model.Item", "ItemID" ) /> |
| | 125 | <cfset Item = beans.ItemManager.load( Item ) /> |
| | 126 | <cfset arguments.event.setValue( "ItemBean", arguments.event.makeEventBean( Item ) ) /> |
| | 127 | </cffunction> |
| | 128 | |
| | 129 | </cfcomponent> |
| | 130 | |
| | 131 | }}} |
| | 132 | |
| | 133 | 5. Create a file named !PlantController.cfc in the /PlantOMatic/controller directory and paste the following code in the body: |
| | 134 | |
| | 135 | {{{ |
| | 136 | |
| | 137 | <cfcomponent output="false" hint="I am a Model-Glue controller." extends="ModelGlue.gesture.controller.Controller" beans="PlantManager"> |
| | 138 | |
| | 139 | <cffunction name="loadList" output="false" access="public" returntype="void" hint="I get a list of plants from somewhere over the rainbow"> |
| | 140 | <cfargument name="event" type="any" /> |
| | 141 | <cfset arguments.event.setValue( "PlantList", beans.plantManager.list() ) /> |
| | 142 | </cffunction> |
| | 143 | |
| | 144 | </cfcomponent> |
| | 145 | |
| | 146 | }}} |
| | 147 | |
| | 148 | 6. Open /PlantOMatic/views/ Form.Item.cfm and prepend the following: |
| | 149 | |
| | 150 | {{{ |
| | 151 | |
| | 152 | <cfsilent> |
| | 153 | <cfimport prefix="uform" taglib="/PlantOMatic/uniform" /> |
| | 154 | <cfset event.copyToScope( variables, "CFUniformConfig,ItemBean,PlantList,xe_HandleSubmitForm" ) /> |
| | 155 | <cfset handleSubmitForm = event.linkto( xe_HandleSubmitForm ) /> |
| | 156 | <cfset bean = event.getValue( "ItemBean" ) /> |
| | 157 | </cfsilent> |
| | 158 | |
| | 159 | }}} |
| | 160 | |
| | 161 | == Putting It All Together == |
| | 162 | |
| | 163 | We've finished working with the Model-Glue XML, !ColdSpring XML, two new Controllers, and the HTML form for Item. Let's test our changes. |
| | 164 | |
| | 165 | 1. At the Saved Shipment screen, click the Display link for one of the Shipments |
| | 166 | 2. Press the New Item button; Your screen will look like the figure below:[[BR]] |
| | 167 | [[Image(training06-1.png, nolink)]] |
| | 168 | |
| | 169 | 3. Next, using the form, add an item, then press the Save button |
| | 170 | 4. Your item will be saved and you will be taken to the Display Shipment screen:[[BR]] |
| | 171 | [[Image(training06-2.png, nolink)]] |
| | 172 | |
| | 173 | ---- |
| | 174 | |
| | 175 | Back: [wiki:Training/Section05 Training Section 5: Mother's Little Helper] |
| | 176 | |
| | 177 | Next: [wiki:Training/Section07 Training Section 7: Crossing the Generational Gap] |