Dynamically adding <views/> to a Model-Glue Event

Mark Drew hit me up with an interesting question this morning: can you dynamically add views to a Model-Glue event, determining which views to include at runtime, what to name them, and what template they should use? Yes, you can, and you can do it without mixing configuration information into the controller tier.

Background Being a stubborn curmudgeon, I asked why he'd want to in the first place: it'd place configuration knowledge (names of templates, names of views) up in the controller tier. Being a logical guy, he told me he was well aware of this, and outlined his situation. To spare you the details, I'll just say that I agree that adding views to the queue at runtime is necessary in his case. The Solution Disclaimer: I'd recommend avoiding situations where doing this is necessary, but it's good to know it can be done! In a Model-Glue controller, if you <cfdump&/> arguments.event, you'll see that you're dealing with an instance of EventContext. It's got a method, getEventRequest(), that lets you hook into the underlying event request. Warning: you can really screw some stuff up by monkeying with the event request. Red text aside, EventRequest has a method called addView(view:View) that lets you add views to the queue of views to be rendered. All we need to do to keep Mark happy is to create an instance of ModelGlue.unity.eventhandler.View and add it to the queue:
<cffunction name="queueDynamicViews" access="public" returnType="void" output="false">
    <cfargument name="event" type="any">

    <cfset var eventRequest = arguments.event.getEventRequest() />
    <cfset var view = createObject("component", "ModelGlue.unity.eventhandler.View").init() />

    <cfset view.setTemplate("dspSomeDynamicView.cfm") />
    <cfset view.setName("dynamicView") />

    <!--- Add our dynamic event to the queue of pending views to render --->
    <cfset eventRequest.addView(view) />
</cffunction>
That's kind of sloppy, though: in Model-Glue 2.0, you can achieve a very high degree separation of configuration from code. Because it's ok to instantiate a View as a singleton (it's just metadata), we can define this view as a ColdSpring bean, autowiring it into our controller. Here's the code: ColdSpring
<bean id="someDynamicView" class="ModelGlue.unity.eventhandler.View">
    <!-- Just like the name attribute on <view>! -->
    <property name="name"><value>dynamicView</value></property>
    <!-- This'll use the viewMappings setting just like a normal view! -->
    <property name="template"><value>dspSomeDynamicView.cfm</value></property>
</bean>
Controller
<cfcomponent displayname="DynamicViewController" extends="ModelGlue.unity.controller.Controller" output="false">

<cffunction name="setSomeDynamicView">
    <cfargument name="someDynamicView" />
    <cfset variables._someDynamicView = arguments.someDynamicView />
</cffunction>
    
<cffunction name="queueDynamicViews" access="public" returnType="void" output="false">
    <cfargument name="event" type="any">

    <cfset var eventRequest = arguments.event.getEventRequest() />
    <cfset eventRequest.addView(variables._someDynamicView) />
</cffunction>

</cfcomponent>
TweetBacks
Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Joe, rather than manually using CreateObject to create the instance of ModelGlue.unity.eventhandler.View, is there a way to get it by calling ColdSpring (using a factory method defined in the ColdSpring XML)?
# Posted By Brian Kotek | 7/17/07 12:23 PM
wait whats going on here?? He is injecting Brian...
# Posted By sal | 8/1/07 11:33 PM
He updated the entry after I posted that comment.
# Posted By Brian Kotek | 8/2/07 1:44 AM
© 2017 Joe Rinehart
BlogCFC was created by Raymond Camden. This blog is running version 5.9.3.006.