You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Bob Harner <bo...@gmail.com> on 2013/10/23 03:21:36 UTC

The Bootstrap Backward Compatibility Problem

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.

Re: The Bootstrap Backward Compatibility Problem

Posted by Lenny Primak <lp...@hope.nyc.ny.us>.
I was the one who pestered you :)
I also like this idea, and now the FormHorizontal mixin is working just like you suggested.

On Oct 23, 2013, at 9:04 AM, Barry Books wrote:

> When I first wrote the tapestry-bootstrap module someone on the list
> pestered me (thanks) to make it backward compatible with the current
> components so you could have both Bootstrap and the older Tapestry
> components on the same page. After some tinkering I discovered it was for
> the most part possible. The biggest issue seems to be something in
> Prototype causes a problem with the Bootstrap menus.
> 
> I've been using Bootstrap the since the 1.0 version and I'm currently
> porting my last non Bootstrap web site to 5.4 and Bootstrap. I'm a big
> Bootstrap fan but I can see it's not for everybody. I would also say for
> better or worse the Bootstrap project does seem to worry too much about
> backward compatibility.
> 
> At this point I'm happy with the direction of Tapestry and I think the
> addition of Bootstrap solves more problems than it causes.
> 
> However I do think it could be better so here is my suggestion
> 
> 1. Components should have no framework specific html elements and no css
> 2. I would make a data attribute called data-tapestry-type contain the
> Tapestry component type.
> 3. Attach a mixin to all components that calls a service to add the
> framework specific markup
> 4. Create a strategy service so various framework markups can be supported.
> 5. Each framework strategy service is a pipeline that takes a markup writer
> and modifies the DOM as needed.
> 6. Create a property to define the default framework.
> 
> This allows any component to be rendered for any framework. It also
> supports new components by adding services to the framework pipeline. You
> can also contribute site specific customization of components. Lastly it
> solves the markup backward compatibility problem because the default markup
> is not specific to any framework and does not need to change.
> 
> This is similar to how the current tapestry-bootstrap modules works.
> 
> The backend implementation can be a bit complex but most developers could
> just drop in the framework module they want and the site magically converts
> to that framework.
> 
> I did have some issues with the existing components when I went down this
> path. There are some inconsistencies in when components add to the markup
> writer but I think these could all be resolved. For example the outer
> element should always be started before the mixin's beginRender method.
> With a bit more consistency I think all framework specific markup could be
> added with a mixin like
> 
> private Element outerElement;
> 
> @Environmental
> private Framework framework;
> 
> @BeginRender
> void beginRender(MarkupWriter writer) {
> outerElement = writer.getElement();
> }
> 
> @CleanupRender
> void cleanupRender(MarkupWriter writer) {
> framework.cleanup(framework, outerElement, writer);
> }
> 
> Personally I would not advocate this change at this point. I think the
> current 5.4 path is fine. If there is enough interest it might be
> interesting in 5.4.1 and along with a tapestry-legacy framework module
> could be helpful for people with older sites wanting to upgrade to 5.4
> 
> Barry
> 
> 
> On Tue, Oct 22, 2013 at 11:59 PM, Lenny Primak <lp...@hope.nyc.ny.us>wrote:
> 
>> I am glad I am not the only one seeing this.
>> It's not an easy problem to solve though.
>> And, I am not one of those people that want 100% compatibility
>> (hence I would gladly have Tapestry 6)
>> 
>> I am in the process of converting an app to Tapestry 5.4,
>> Having never used bootstrap, and not being a web designer myself,
>> it presented a challenge, but not insurmountable one.
>> The ongoing problem is indeed that the markup will change over time,
>> and maintaining compatibility will be problematic.
>> 
>> Right now, My particular issue is beaneditform with <p:> parameters
>> isn't generating proper bootstrap markup.
>> I am sure there will be other issues like this that I discover.
>> 
>> On Oct 22, 2013, at 9:21 PM, Bob Harner wrote:
>> 
>>> 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.
>> 
>> 
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
>> For additional commands, e-mail: dev-help@tapestry.apache.org
>> 
>> 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org


Re: The Bootstrap Backward Compatibility Problem

Posted by Barry Books <tr...@gmail.com>.
When I first wrote the tapestry-bootstrap module someone on the list
pestered me (thanks) to make it backward compatible with the current
components so you could have both Bootstrap and the older Tapestry
components on the same page. After some tinkering I discovered it was for
the most part possible. The biggest issue seems to be something in
Prototype causes a problem with the Bootstrap menus.

I've been using Bootstrap the since the 1.0 version and I'm currently
porting my last non Bootstrap web site to 5.4 and Bootstrap. I'm a big
Bootstrap fan but I can see it's not for everybody. I would also say for
better or worse the Bootstrap project does seem to worry too much about
backward compatibility.

At this point I'm happy with the direction of Tapestry and I think the
addition of Bootstrap solves more problems than it causes.

However I do think it could be better so here is my suggestion

1. Components should have no framework specific html elements and no css
2. I would make a data attribute called data-tapestry-type contain the
Tapestry component type.
3. Attach a mixin to all components that calls a service to add the
framework specific markup
4. Create a strategy service so various framework markups can be supported.
5. Each framework strategy service is a pipeline that takes a markup writer
and modifies the DOM as needed.
6. Create a property to define the default framework.

This allows any component to be rendered for any framework. It also
supports new components by adding services to the framework pipeline. You
can also contribute site specific customization of components. Lastly it
solves the markup backward compatibility problem because the default markup
is not specific to any framework and does not need to change.

This is similar to how the current tapestry-bootstrap modules works.

 The backend implementation can be a bit complex but most developers could
just drop in the framework module they want and the site magically converts
to that framework.

I did have some issues with the existing components when I went down this
path. There are some inconsistencies in when components add to the markup
writer but I think these could all be resolved. For example the outer
element should always be started before the mixin's beginRender method.
With a bit more consistency I think all framework specific markup could be
added with a mixin like

private Element outerElement;

@Environmental
private Framework framework;

@BeginRender
void beginRender(MarkupWriter writer) {
outerElement = writer.getElement();
}

@CleanupRender
void cleanupRender(MarkupWriter writer) {
framework.cleanup(framework, outerElement, writer);
}

Personally I would not advocate this change at this point. I think the
current 5.4 path is fine. If there is enough interest it might be
interesting in 5.4.1 and along with a tapestry-legacy framework module
could be helpful for people with older sites wanting to upgrade to 5.4

Barry


On Tue, Oct 22, 2013 at 11:59 PM, Lenny Primak <lp...@hope.nyc.ny.us>wrote:

> I am glad I am not the only one seeing this.
> It's not an easy problem to solve though.
> And, I am not one of those people that want 100% compatibility
> (hence I would gladly have Tapestry 6)
>
> I am in the process of converting an app to Tapestry 5.4,
> Having never used bootstrap, and not being a web designer myself,
> it presented a challenge, but not insurmountable one.
> The ongoing problem is indeed that the markup will change over time,
> and maintaining compatibility will be problematic.
>
> Right now, My particular issue is beaneditform with <p:> parameters
> isn't generating proper bootstrap markup.
> I am sure there will be other issues like this that I discover.
>
> On Oct 22, 2013, at 9:21 PM, Bob Harner wrote:
>
> > 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.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: dev-help@tapestry.apache.org
>
>

Re: The Bootstrap Backward Compatibility Problem

Posted by Lenny Primak <lp...@hope.nyc.ny.us>.
I am glad I am not the only one seeing this.
It's not an easy problem to solve though.
And, I am not one of those people that want 100% compatibility
(hence I would gladly have Tapestry 6)

I am in the process of converting an app to Tapestry 5.4,
Having never used bootstrap, and not being a web designer myself,
it presented a challenge, but not insurmountable one.
The ongoing problem is indeed that the markup will change over time,
and maintaining compatibility will be problematic.

Right now, My particular issue is beaneditform with <p:> parameters
isn't generating proper bootstrap markup.
I am sure there will be other issues like this that I discover.

On Oct 22, 2013, at 9:21 PM, Bob Harner wrote:

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


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org