VIew Tip: Using CopyToScope()

Another tip in our series of keeping code simple in our view layer.  A lot of developers copy event-args into the variables cope at the top of a view to make looping and other miscellaneous display logic more manageable.  This bit of code becomes more complex as our views get more complex.  Take this example:

 <cfimport prefix="view" taglib="/MachII/customtags/view" />
 <cfimport prefix="display" taglib="/lightpost/cftags/display/" />
 <cfscript>
     // Get data
     variables.adminBean = event.getArg("adminBean");
     variables.formattedName = event.getArg("adminBean").getFormattedName();
     variables.adminAnpBean = event.getArg("adminAnpBean");
     variables.adminAddressBean = event.getArg("adminAddressBean");
     variables.adminPrimaryPhoneBean = event.getArg("adminPrimaryPhoneBean");
     variables.adminSecondaryPhones = event.getArg("adminSecondaryPhones");
     variables.locations = event.getArg("assignedLocations");
     // Get services
     variables.timeService = getProperty("timeService");
     variables.uiService = getProperty("uiService");
     variables.udfs = getProperty("udfs");
     // Set meta data into the event object
     getProperty("html").addMeta("title", "Administrator Details for #variables.adminBean.getFormattedName()##");
     event.setArg("meta.cacheControl", TRUE);
 </cfscript>
 

Ouch, that is a bit of code to manage.  If you look carefully, you'll notice that most copies of args from the event have the same name when assigned to the variables scope (except for a few which we'll talk about later).  This can be simplified by using the new copyToScope() method available in Mach-II 1.8+:

     <cfimport prefix="view" taglib="/MachII/customtags/view" />
     <cfimport prefix="display" taglib="/lightpost/cftags/display/" />
     <cfset copyToScope("${event.adminBean}
             ,${event.adminBean.formattedName}
             ,${event.adminAnpBean}
             ,${event.adminAddressBean}
             ,${event.adminPrimaryPhoneBean}
             ,${event.adminSecondaryPhones}
             ,locations=${event.assignedLocations}
             ,${properties.timeService}
             ,${properties.uiService}
             ,${properties.udfs}") />
     <view:meta type="title" content="Administrator Details for #variables.formattedName#" />
     <cfset event.setArg("meta.cacheControl", TRUE) />
 

Wow! That's a lot less code than before.  Let's look at two special cases.  If you compared the two code blocks, notice that ${event.adminBean.formattedName} is not only getting the admin bean, but also making a call to a getter.  CopyToScope() uses the Mach-II Expression Language Syntax and if an object (CFC) is selected, it will dive deeper and call methods.  If you don't append a () a the end, the framework assumes you are calling a getter so behind the scenes it is really calling getFormattedName() for you.  Secondly, noticed that locations=${event.assignedLocations} is setting a different key name.  By default we use the last value in the dot path of the M2 EL syntax as the key name in the variables scope so in this case we'll set the data in "locations" instead of "assignedLocations".

Check out the CopyToScope documentation for more information on using deeply nested data and other nifty features.