RE: [coldbox:3652] Arguments for RunEvent or Viewlet

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. :slight_smile:

~Brad

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.

  1. 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

@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.

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

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

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.