Sorry if I wasn't clear. While I am interested in wrapping view output
in a layout container, and potentially wrapping that layout's output
in another layout etc, that's not what I was getting at in talking
about view and layout CFCs and inheritance among them.
There are some utility-level functions that I'd like to have available
to all views, things like renderHTMLSelectOptionsFromArray,
renderCheckboxRadio, renderCheckboxRadioSet, and so on. It's also
common to want certain widget rendering functions in related views;
for instance UserView.profileEdit and UserView.admin may both want
renderUserCategorySelect. Individual views may also have rendering
utilities unique to them, broken out into separate functions not
because they're common to multiple views, but for readability -- I
rather see renderPhoneNumbers(phoneData) in a view than the actual
code to iterate over that data and output a series of fields and the
javascript to edit them inline.
To me, the cleanest way to handle all of this is to built views as CFC
methods. Locally unique helper functions are just methods of the view
CFC that needs them. So are methods common to various domain-specific
views; UserView contains renderUserCategorySelect, for example.
Generic things like renderHTMLSelectOptionsFromArray go in BaseView,
from which all views eventually inherit. If you need it, methods
common to a series of view CFCs go in an intermediate base class that
extends BaseView, and that the relevant individual views extend. If
you're returning raw data from some ajax calls (rather than HTML), you
may have some JSON or XML rendering utilities you could put in an
BaseAjaxView class (a little contrived, and there may be better
approaches, but you get the idea).
You may also find that there are some useful pseudo-constants you
could declare in the init code for a view or base view, things like
HTML_SELECT_OPTION_NONE = '-- select --', or whatever you like.
Completely universal "language extensions" and CFML-version-leveling
tools like structMake and arrayMake can go in a BaseCFC that BaseView
and other base classes extend. So do shortcut "constants" like CR, LF,
CRLF, and TAB.
If the code for a view gets uncomfortably big, a view method can
cfinclude a separate file, leaving only the argument and local 'var'
declarations in the CFC method itself.
So views aren't objects in the sense that they represent business
logic, or have instance data. Still, they can be built as singletons
that inherit from a BaseView containing whatever common utilities you
want, and possibly from more specific base classes with methods common
to some set of view classes.
I see this approach as an organized, organic, and encapsulated
approach to view helpers. Yes views are "just templates", but they've
got code in them, some of which is highly reusable, and they're
related in various ways to other views, and even somewhat to non-view
components. There's no reason to think of views as unique creatures
that need a completely different approach to reuse and
interrelatedness than everything else. The fact that
jsp/Velocity/Smarty/insert-favorite-templating-engine-here don't do
this doesn't mean we can't.
I certainly don't mean to criticize ColdBox, any other framework, or
their makers or users; they deserve a huge amount of respect. I'm just
talking about another way I've built views in the past, sans
framework, and why that works for me. The fact that that approach
isn't available in any frameworks I'm aware of may mean that I have
poor judgment and should be ignored (:-). Or maybe it's something
worth thinking about.
Dave