Skip to content

GroupRenderer (h:panelGroup): widen wrapper gate to any renderable attribute / attached behavior #5792

Description

@BalusC

Summary

GroupRenderer decides whether to emit a wrapper element (div/span) around h:panelGroup based on too narrow a gate. It should also emit the wrapper when the component carries any passthrough attribute or an attached client behavior — matching MyFaces and the rendering contract just clarified in the Faces spec.

Background

Jakarta Faces jakartaee/faces#2182 found that the four normative doc sources for the jakarta.faces.Group renderer contradicted each other and reality. jakartaee/faces#2186 (targeting 5.0) resolved this doc-only, standardizing on the broader MyFaces "any renderable attribute" gate as the specified minimum:

A wrapper element is rendered when the component has a renderable client id, or any renderable attribute is present (style, styleClass, any passthrough attribute, or an attached client behavior). When a wrapper element is rendered, a value of "block" for the layout attribute produces a div; any other value (or an absent layout) produces a span.

This issue is the Mojarra impl counterpart of that doc change.

Current behavior

GroupRenderer.divOrSpan gates the wrapper on id / style / styleClass only:

private boolean divOrSpan(UIComponent component) {
    return shouldWriteIdAttribute(component)
        || component.getAttributes().get("style") != null
        || component.getAttributes().get("styleClass") != null;
}

So a panelGroup that carries a passthrough attribute or an attached behavior but no id/style/styleClass emits no wrapper — yet encodeBegin still calls RenderKitUtils.renderPassThruAttributes(...), so those attributes (and behavior hooks) have no element to land on. Examples that misbehave today:

  • <h:panelGroup onclick="..."> / role, dir, lang, title, …
  • <h:panelGroup><f:passThroughAttribute name="data-x" value="y"/></h:panelGroup>
  • <h:panelGroup><f:ajax event="click" .../></h:panelGroup>

These would only work in Mojarra if the <h:panelGroup> has an explicit id, styleClass or style attribute.

Reference impl

MyFaces HtmlGroupRendererBase.encodeEnd already gates on the broader condition: renderable id, non-empty behaviors, or any passthrough/universal attribute present.

Proposed fix

Widen divOrSpan so it also returns true when the component has any renderable passthrough attribute or an attached client behavior, then div vs span selection by layout proceeds as today. File: impl/src/main/java/org/glassfish/mojarra/renderkit/html_basic/GroupRenderer.java.

Out of scope

Treating an explicit layout as an unconditional box trigger (so <h:panelGroup layout="block"/> always emits an empty div) is a separate behavior change requiring an EG decision and a spec version gate — see option (a) in jakartaee/faces#2182. Not part of this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions