Arguments for RunEvent or Viewlet

71 views
Skip to first unread message

Seth

unread,
Dec 22, 2009, 10:41:40 AM12/22/09
to ColdBox Platform
Hey all, I need some advice or help changing the way I'm thinking.

Context: an authenticated user main page that is composed of several
distinct views, for example, a list of products by date.

Goals: separate view and business logic; encapsulate business logic in
an event for each composing view so that it can be used in other areas
of the site without duplicating code and so that the main event for
the page isn't too big/complicated to easily maintain.

My first instinct was to use runEvent from the main event to pull in
all of the data needed to render each view. However, I don't see any
way to pass the variable(s) with runEvent. My instincts are against
putting the variable(s) into the request collection and pulling it out
again. It feels very procedural, and I'm concerned about collision.
To me it seems as though the called event should be able to recieve
arguments and should itself decide if it needs to place any of those
arguments into the request collection. If the delegated event were in
the same handler as the main event, I could call it directly as a
method, however it is (and should be) in a different handler.

My second instinct was to use the 'viewlet' pattern and run the event
at the top of the viewlet file. However that seems to put too much
logic into the view code for my comfort. Since this viewlet (search
results) may be reused in several places in the application, I would
have to figure out how it's being used to determine what values to
search by. And then I still have to put those into the request
collection and run the event.

Is there a way I can do this?

Dorioo

unread,
Dec 22, 2009, 4:13:28 PM12/22/09
to col...@googlegroups.com
Where are the arguments that you'd want to pass to the event or the viewlet coming from? URL or Form values? Or something else?

- Gabriel


--
You received this message because you are subscribed to the Google Groups "ColdBox: A ColdFusion Framework" group.
To post to this group, send email to col...@googlegroups.com
To unsubscribe from this group, send email to coldbox-u...@googlegroups.com
For more options, visit this group at http://groups-beta.google.com/group/coldbox
For more information, visit http://www.luismajano.com/projects/coldbox
For Documentation, visit http://ortus.svnrepository.com/coldbox/trac.cgi

br...@bradwood.com

unread,
Dec 22, 2009, 10:51:33 PM12/22/09
to col...@googlegroups.com
Perhaps Seth won't mind me jumping in here since I think he's at home
under the weather tonight and I believe I am a little familiar with
where he is going. The source of the arguments is mostly irrelevant I
believe-- the important part is that they are specific to the piece of
content being included and simply don't seem to fit anywhere.

To go back to Seth's example of a product list being included multiple
places in a site, one of the pieces of data that view needs is the
actual result set or array of product objects it will be using to loop
over and create the actual HTML output. The logic to retrieve that data
isn't something the view should be doing-- that is the job of a
controller to ensure the data necessary for the view to display is
present in the request collection prior to the view code being run.
Another hypothetical parameter could be some flags dictating the view
code how to render itself. This product list may be included in 5
separate places on the site, and the height and width of the table might
be different based on what screen it is being included on. Those
variables would likely be set at the point in which the product list was
asked to render itself.

To spell it out-- the problem with asking the product service for the
data to render the view in ALL FIVE handlers and then just doing
renderView() in your main view is because our theoretical product list
shows up on 5 separate pages of our site-- which means that 5 distinct
(and unrelated) events all need to ask the product service for its data
and shove it into the request collection-- but this doesn't seem to make
the product list be an encapsulated little package you can "drop into" a
page. It also doesn't make it very intuitive for other programmers
modifying the code to know where that data is being set into the request
collection.

If you could simply call runEvent() somewhere and fire off the product
list handler to get the data and its view to loop over and output it,
and wrap up all the resultant HTML of that event (minus any layouts) in
a variable and then stick THAT chunk of HTML into your main view that
would be a little more encapsulated since you aren't spreading the
pieces all over, however I think Seth's main problem there is he doesn't
want to "bloat" the main request collection with the data that only the
product list needed when it isn't necessary to display the main view and
might interfere with variable names in the the request collection for
the main page. Additionally, if the main event/view wanted a way to let
the product list view know how wide to display itself, there doesn't
seem to be a direct way to pass those parameters in to the product list
event-- you sort of just throw them in to the all-transcending request
collection and let the view "catch" them.

Keep in mind this is a compounding problem. In reality we have far more
than a single chunk we want to reuse-- we have tons of these little
stand-alone reusable "pods" that we use all over our site. It is really
getting to be a mess when the main handler has to load up ALL SORTS of
unrelated pieces of information which are VERY loosely coupled to all
the views that are going to be individually rendered as they
parasitically suck what they need out of a very large request
collection.

Speaking personally here-- back when I used to use Fusebox 3 or so it
would let you include a fuse action anywhere you wanted by simply
calling it as a custom tag with cfmodule. This invoked it's own little
recursive instance of a Fusebox request loaded up with whatever
attributes you chose to pass in right there. The fuse action you
cfmoduled in was 100% self-sufficient, didn't require any variables in a
persisted scope to be (hopefully) loaded up into the containing fuse
action, and you could very explicitly pass any additional attributes
directly into the inner fuse action without cluttering up your main
attribute collection. That sort of package-able drop-in approach worked
very well for reusable little sections we could place anywhere in the
site. I think that sort of encalpsulated functionality is what Seth is
pining for.

I'm sure Seth with correct me if I have strayed, but that is my
understanding of the issue. :)

~Brad

Dorioo

unread,
Dec 23, 2009, 12:00:33 AM12/23/09
to col...@googlegroups.com
Just brainstorming and thinking out loud.

1. If the goal is encapsulation and not necessarily the features of an event, would a plugin or a model object that returned the html work for you?

So that in one event, the controller would call
     PRC.myHTMLCodeInEventA = productService.getProductsAsStanderizedHTMLPod(width=300)

And in another event, it could change the appearance as needed for that event
     PRC.myHTMLCodeInEventB = productService.getProductsAsStanderizedHTMLPod(width=100)

The view would then render the PRC value where needed.

2. If the product service data and its appearance are truly standardized and reusable, I'd be comfortable with having my service or a plugin return that data and have my controller pass whatever custom arguments are needed in the call (e.g. width above).

For example, I saw a plugin that handles pagination, takes a query and some other arguments as input, and returns html to be included in the view. Because the html from the pagination plugin is standardized and reusable, I consider the whole thing as data that's no different than returning a JSON string or XML.

- Gabriel

Seth

unread,
Dec 23, 2009, 11:30:10 AM12/23/09
to ColdBox Platform
@Brad: Thanks for jumping in with some more detail. Yeah, that's all
accurate.

@Gabriel:

I'm not very keen on having my view code returned by the service which
is part of the model, but I'll consider that. Ideally I could
delegate to another handler without stuffing everything in the request
collection, but Coldbox doesn't allow that. I even played around a
bit yesterday with the preEvent and preHandler interceptors but by the
time they are invoked any extra arguments added to runEvent are not
present.

I guess my biggest beef is that runEvent is intended for delegating
and chaining events together, but as Brad said it depends on the
request collection for passing arguments. What I'd like to see is for
it to accept a querystring argument like setNextEvent that could be
either a string or an struct that would get passed along to the event.

Another possibility might be to run the events for these viewlets with
AJAX after the page loads.

On Dec 22, 11:00 pm, Dorioo <dor...@gmail.com> wrote:
> Just brainstorming and thinking out loud.
>
> 1. If the goal is encapsulation and not necessarily the features of an
> event, would a plugin or a model object that returned the html work for you?
>
> So that in one event, the controller would call
>      PRC.myHTMLCodeInEventA =
> productService.getProductsAsStanderizedHTMLPod(width=300)
>
> And in another event, it could change the appearance as needed for that
> event
>      PRC.myHTMLCodeInEventB =
> productService.getProductsAsStanderizedHTMLPod(width=100)
>
> The view would then render the PRC value where needed.
>
> 2. If the product service data and its appearance are truly standardized and
> reusable, I'd be comfortable with having my service or a plugin return that
> data and have my controller pass whatever custom arguments are needed in the
> call (e.g. width above).
>
> For example, I saw a plugin that handles pagination, takes a query and some
> other arguments as input, and returns html to be included in the view.
> Because the html from the pagination plugin is standardized and reusable, I
> consider the whole thing as data that's no different than returning a JSON
> string or XML.
>
> - Gabriel
>

br...@bradwood.com

unread,
Dec 23, 2009, 11:38:35 AM12/23/09
to col...@googlegroups.com

> Another possibility might be to run the events for these viewlets with
> AJAX after the page loads.


Man, I just KNEW someone would say "Use jQuery"-- I just didn't think it
would be you, Seth!

:)

~Brad

br...@bradwood.com

unread,
Dec 23, 2009, 11:43:53 AM12/23/09
to col...@googlegroups.com
Interesting suggestion. Like Seth, I hadn't really considered
generating HTML from the model or a plugin since it just didn't "feel"
right. I don't want to hi-jack Seth's thread at all, but I would like to
hear an elaboration on what you consider "standardized HTML". Do you
just mean that the HTML is the same every place it is included (with the
exception of a variable width or something).

Thanks.

Dorioo

unread,
Dec 23, 2009, 11:45:23 AM12/23/09
to col...@googlegroups.com
Another thought (may not work. never tried it)

If you're running coldbox 3.0, there is a flash ram object that's used to persist data between requests. If your desire it to pass information outside of the request collection, maybe it can be used to pass your configuration string or struct to the viewlet. So something like:

1. Handler adds the string or struct information to the flash ram object
2. Handler's view executes a viewlet
3. Viewlet looks in the flash ram for configuration string or struct. Does a default thing otherwise.

Don't know if it would work but I know the flash ram object is available in the handler and the view so I assume it would also be available in a viewlet's handler and view

- Gabriel

Judah McAuley

unread,
Dec 23, 2009, 11:50:16 AM12/23/09
to col...@googlegroups.com
Have you considered the new private request collection in CB 3.0? It
is uneffected by the form/url/remote variables and seems like it might
be what you're looking for. Set up a struct in the private request
collection that contains the data you want to pass and treat it as
your own store of event-specific data that gets passed along to
runEvent.

Judah

Dorioo

unread,
Dec 23, 2009, 12:13:20 PM12/23/09
to col...@googlegroups.com
@brad,

Yup. If the HTML is exactly the same every place that it's included (except for parts that have been abstracted into arguments like the width), then I can stop thinking it about it as HTML and look at it as a custom format with defined rules to its structure, just like XML or JSON, that just so happens to render as HTML.

So from my model or plugin's perspective, it's simply returning a structure using the arguments you provide. It then falls to the controller and view to coordinate in making the returned structure (the "standerized" html) look as it should.

- Gabriel

Seth

unread,
Dec 23, 2009, 12:29:03 PM12/23/09
to ColdBox Platform
We haven't upgraded to 3.0 yet, but that might be an option. Maybe I
just need some sort of namespace convention in the request collection
for arguments for runEvents.

On Dec 23, 10:50 am, Judah McAuley <judah.mcau...@gmail.com> wrote:
> Have you considered the new private request collection in CB 3.0? It
> is uneffected by the form/url/remote variables and seems like it might
> be what you're looking for. Set up a struct in the private request
> collection that contains the data you want to pass and treat it as
> your own store of event-specific data that gets passed along to
> runEvent.
>
> Judah
>
> On Wed, Dec 23, 2009 at 8:45 AM, Dorioo <dor...@gmail.com> wrote:
> > Another thought (may not work. never tried it)
>
> > If you're running coldbox 3.0, there is a flash ram object that's used to
> > persist data between requests. If your desire it to pass information outside
> > of the request collection, maybe it can be used to pass your configuration
> > string or struct to the viewlet. So something like:
>
> > 1. Handler adds the string or struct information to the flash ram object
> > 2. Handler's view executes a viewlet
> > 3. Viewlet looks in the flash ram for configuration string or struct. Does a
> > default thing otherwise.
>
> > Don't know if it would work but I know the flash ram object is available in
> > the handler and the view so I assume it would also be available in a
> > viewlet's handler and view
>
> > - Gabriel
>

> ...
>
> read more »

br...@bradwood.com

unread,
Dec 23, 2009, 12:51:55 PM12/23/09
to col...@googlegroups.com
I'm not immediately familiar with the private request collection but I
assume there is still only one of these private collections for the
entire request. If that is the case, that doesn't really address the
issue of it being bloated with unrelated keys with possible name
collosions-- it only mitigates it slightly.

I think Seth's idea of a well-named struct for all data needed for a
certain view at least addresses the latter issue.

Reply all
Reply to author
Forward
0 new messages