For new projects it's very nice that Tapestry 5.4 uses and includes
Bootstrap. But for existing 5.2 and 5.3 projects not already using
Bootstrap (which is probably the vast majority), upgrading to 5.4 requires
a burdensome amount of CSS and HTML changes. Even if you go the route of
eliminating the Bootstrap CSS file (which for large existing apps may be
the only practical option), you still need to come up with all new CSS
rules for the built-in Tapestry components -- Grid, BeanEditor, Palette,
etc -- on your own.

Back in August, Tapestry 5.4-alpha-18 switched from Bootstrap 2 to
Bootstrap 3. Since 2 and 3 are incompatible, this meant Howard had to do
another round of disruptive, non-backward-compatible changes to Tapestry
components (see his commits between Aug 21 and Sep 3, for TAP5-2151), and
all users tracking the alphas had to adapt their apps to use Bootstrap 3.
What happens if you wanted to stick with Bootstrap 2? What happens when
Bootstrap 4 comes out?

As we all know, one of Tapestry's "core principles" is backward
compatibility -- which means upgrades should be very easy.

It occurred to me that Tapestry already has a built-in means for rendering
alternate content for the same components -- the template skinning
mechanism (http://blog.tapestry5.de/index.php/2011/06/24/template-skinning/).
Could this mechanism be used for the Bootstrap compatibility problem?
 Could Tapestry use Template Skinning internally to choose between
"Bootstrap 2", "Bootstrap 3" and "Tapestry Classic" templates based on a
configured symbol?

One obstacle is that most of Tapestry's built-in components render the CSS
class names and layout directly from the component class (using
MarkupWriter) rather than using a template. In the cases I looked at,
though, this could be changed. For example, TextField's has this:

writer.element("input","type",type,"name", getControlName(),"class",
"form-control","id", getClientId(),"value", value,"size", getWidth());

but that could be moved to a TextField.tml file:

<input type="${type}" name="${controlName}" class="form-control"
id="${clientId}" value="${value}" size="${width}" />

It's not quite that simple, of course. The templates might end up with some
"if" statements wrapped around some sections to handle logic that now
resides in the component class. But that's okay, because it still allows us
to have alternate versions of the templates for different skins/themes.

By my count there are 14 components that have Bootstrap-related rendering
(Alerts, BeanEditForm, BeanEditor, Checkbox, Checklist, ControlGroup,
DateField, Errors, Palette, PasswordField, Radio, Select, TextArea,
TextField), and of those, only BeanEditForm/BeanEditor, Checklist use
templates.

Reply via email to