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?
--
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
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
@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
>
> 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
Thanks.
Judah
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 »
I think Seth's idea of a well-named struct for all data needed for a
certain view at least addresses the latter issue.