panelGroup without style or styleClass is not rendered unless ID is given - jsf

According to the tag library for http://xmlns.jcp.org/jsf/html, a h:panelGroup is
Intended for use in situations when only one
UIComponent child can be nested, such as in the case of facets.
If the "style" or "styleClass" attributes are present, and the
"layout"
attribute is present with a value of "block", render a "div"
element,
outputting the value of the "style" attribute as the value of the
"style" attribute and the value of the "styleClass" attribute as the
value of the "class" attribute. Otherwise, if the "layout" attribute
is not present, or the "layout" attribute contains a value other
than
"block", render a "span" element, outputting the value of the
"style" attribute as the value of the "style" attribute, and the
value
of the "styleClass" attribute as the value of the "class"
attribute.
In case of
<h:panelGroup id="id" layout="block">
<!-- ... --->
</h:panelGroup>
or
<h:panelGroup layout="block" style="margin-right: 10px;">
<!-- ... --->
</h:panelGroup>
a div is being rendered:
<div id="id">
</div>
respective
<div style="margin-right: 10px;">
</div>
but when omitting the id (if one don't want to update the panelGroup) or the style (if one don't want to style the panelGroup) no div is being rendered and the resulting HTML can mess up ones layout. Furthermore exploring the realm of JSF, a panelGroup can also be used to conditionally render child elements using its rendered flag but as mentioned before when omitting the two mentioned attributes the result is rendered conditionally but without a div, such as
<h:panelGroup layout="block" rendered="true">
<it>Without DIV.</it>
</h:panelGroup>
leads to
<it>Without DIV.</it>
After this inquiry I want to check with the Stackoverflow community that I understood it right that when not using a panelGroup as a naming container or to customary style its elements one is better off solving the conditional rendering part (if needed) using a ui:fragment and the layouting part with a hard-coded div. Is this so?

Note: we are talking about if h:panelgroup will render any HTML component, but unless render="false" the inner components are not blocked from rendering in any case.
The behaviour tree of h:panelgroup consists of two checks:
Is at least one of "id" or "style" or "styleClass" attributes set?
Yes:
a. Renders a <div> if layout="block", otherwise
b. Renders a <span> (layout="gibberish" or non-existant)
No:
Renders no html component. Still useful if you want to use "rendered" or when you can nest only one component (i.e. <f:facet>)
The test for the layout attribute only comes after 1., above. Since your third example goes into the no branch, it is ignored.

Related

JSF id value to the component behaves different

I have the following code in my xhtml
<h:form id="xyForm">
<p:dataGrid id="xyGrid" ....>
<p:selectOneMenu id="code" ...> </p:selectOneMenu>
</p:dataGrid>
</h:form>
But when I saw the code generated, it looks like the following
<select name="xyForm:xyGrid:0:code_input" tabindex="-1" id="xyForm:xyGrid:0:code_input"> </select>
My question here is: why _input is getting appended with name and id.
As per my understanding id should be only xyForm:xyGrid:0:code not with appended _input. Could someone please clarify or tell me how to remove that _input?
An id attribute should be unique within an html page.
While rendering the SelectOneMenu, the select tag is wrapped inside a div tag. The div tag will have the id of the component i.e. xyForm:xyGrid:0:code, and so it makes sense that the select tag should have a different id.
Also, this is a common pattern in Primefaces, observed in other components like SelectBooleanCheckbox etc.
Instead of trying to removing _input, you will have to figure around how to work around it.

JSP Custom Tag File and Dynamic attributes

I have a custom JSP tag tag file, which is a wrapper around HTML input controls - dropdown etc, like so -
<mytag:dropdown table="customer_master" style="display:block;" class="dblist"/>
Here "table" is a declared attribute of the tag where as style, class are dynamic-attributes.
Now I would like to wrap this is in another tag like so -
<mytag:search-filter type="dropdown" validate="true" table="mytable" style="display:block;" class="dblist">
I am trying to implement mytag:search-filter as follows -
<#tag .... dynamic-attributes="dynattrs">
<#attribute name="type" required="true">
<c:if test="${type == 'dropdown'}">
<mytag:dropdown table="$dynattrs['table']">
</c:if>
The outer tag has its own set of declared attributes and I want the inner tag's attributes to be passed in as dynamic attributes to the outer tag.
The outer tag will then pass its dynamic attributes to the inner tag
I have tried the following and none of them seem to work -
<c:set var="attrs">
<c:forEach items="${dynattrs}" var="a">
${a.key}="${a.value}"
</c:forEach>
</c:set>
<mytag:dropdown table="$dynattrs['table']" ${attrs}/>
The above gives a "Unterminated Tag %lt;mytag:dropdown" Error
<mytag:dropdown table="$dynattrs['table']">
<c:forEach items="${dynattrs}" var="a">
<jsp:attribute name="${a.key}" trim="true">${a.value}</jsp:attribute>
</c:forEach>
</mytag:dropdown>
** The above does not throw any error, but the attribute value inside the inner tag is always empty.
Constraints I have :
a) I want to stick to tag files and do not want to use Java class implementation of TagSupport.
b) As far as possible, do not want to change the inner tag implementation because it is widely used in its current form and any change to it means a huge effort on rework.
Is it possible to achieve what I am trying to do ?
Why do the above not work (especially the second one) ?

<a jsf:rendered="#{...}"> is not interpreted as passthrough element

I don't understand why this piece of code is working:
<h:link value="Login" rendered="#{sessionBean.userInSessionBean == null}" />
and this piece of code is not working:
<a jsf:rendered="#{sessionBean.userInSessionBean == null}">Login</a>
A HTML element will only become a passthrough element if following conditions are met:
There's at least one jsf:xxx attribute from http://xmlns.jcp.org/jsf namespace.
There's at least one "identifying attribute" associated with a specific JSF component.
For the <a> element an identifying attribute is necessary so JSF can decide whether to interpret it as <h:commandLink>, <h:outputLink> or <h:link>. Without an identifying attribute, JSF wouldn't have any idea what component you actually meant to use, so any jsf:xxx attributes will be ignored. The jsf:rendered is not sufficient as identifying attribute because it appears on every single JSF component, so JSF would still have no idea which one you meant.
Given that you seem to intend to have a <h:link>, then use jsf:outcome as identifying attribute.
<a jsf:outcome="login" jsf:rendered="#{empty sessionBean.userInSessionBean}">Login</a>
A completely different alternative is to wrap plain HTML in an <ui:fragment rendered>. See also How to conditionally render plain HTML elements like <div>s?

How to hide elements in JSF?

Is it possible to hide a div etc based on a condition (like you do in rendered attribute with EL) without having to wrap it in a <h:panelGrid ...> etc with a rendered attribute? It ruins my layout. I just need it for the logic, not the layout.
first of all you should not wrap your elements with h:gridPanel which results in html table
instead you should wrap with h:panelGroup which results in span in html code , you can also add layout="block" to h:panelGroup to make it rendered as div
second you dont not use jstl when hiding div instead do something like this
<div style="display:#{(myBean.hideSomeDiv)?'none':'block'}">My Div Content</div>
or
<h:panelGroup styleClass="#{(myBean.hideSomeDiv)?'hide':''">My Span Content</h:panelGroup>
where in css file add this :
.hide {
display: none;
}
INMO you always better hide in JSF with rendered="#{myBean.renderCondition}"
Take a look at BalusC over here Conditionally displaying JSF components
You could just do this:
<div style="display:#{yourBean.property}"></div>
Where yourBean.property would return 'none' to hide the div

Specify conditional rendering of element inside <ui:repeat>? The <c:if> does not seem to work

I am trying to conditionally build a custom list using <ui:repeat>. On every occurrence of -1 as item-value in list, I need to add a line break.
I tried to use <c:if> inside <ui:repeat> for that, but it does not seem to work. It always evaluates false.
<ul>
<ui:repeat value="#{topics.list}" var="topicId" >
<li>#{topicId}</li>
<c:if test="#{topicId eq -1}"> <br/> </c:if>
</ui:repeat>
</ul>
Is this possible?
Not with JSTL tags, no. They run during view build time, not during view render time. You can visualize it as follows: when JSF builds the view, JSTL tags run from top to bottom first and the result is a pure JSF component tree. Then when JSF renders the view, JSF components run from top to bottom and the result is a bunch of HTML. So, JSTL and JSF don't run in sync as you'd expect from the coding. At the moment your <c:if> JSTL tag tag runs, the #{topicId} variable which is set by <ui:repeat> JSF component isn't available in the scope.
Instead of using <c:if>, you need to specify the condition in the rendered attribute of the JSF component of interest. As you've actually none, you could wrap it in a <ui:fragment>.
<ul>
<ui:repeat value="#{topics.list}" var="topicId" >
<li>#{topicId}</li>
<ui:fragment rendered="#{topicId eq -1}"><br/></ui:fragment>
</ui:repeat>
</ul>
Alternatives are <h:panelGroup>
<h:panelGroup rendered="#{topicId eq -1}"><br/></h:panelGroup>
or in your specific case <h:outputText escape="false">
<h:outputText value="<br/>" escape="false" rendered="#{topicId eq -1}" />
as both also emits nothing else to the HTML output when no client side attributes are specified.
See also:
JSTL in JSF2 Facelets... makes sense?
Unrelated to the concrete problem, that's the wrong place for a <br/>. It would be ignored by any webbrowser respecting the HTML specification. Don't you mean it to be inside the <li>? Or better, give it a class and let CSS give it a margin-bottom.

Resources