how to remove worthless tags from jsf f:selectItem - jsf

I will create a list with checkbox. Anything like gmail mail box. I use h:selectManyCheckbox , f:selectItem in HTML table tag. But jsf tags, itselft create a table and destruct my form. How can id say to jsf tags that just create input tag not anymore?
the following is a peace of my code:
<tbody>
<h:selectManyCheckbox value="#{MemberControl.selectedUser}">
<c:forEach items="#{MemberSearchControl.members}" var="member" varStatus="status">
<tr>
<td><f:selectItem itemValue="#{member.id}"></f:selectItem> </td>
<td><span>#{member.lastName}</span></td>
<td><span>#{member.firstName}</span></td>
<td><span>#{member.shareCount}</span></td>
<td><span>#{member.phone}</span></td>
</tr>
</c:forEach>
</h:selectManyCheckbox>
</tbody>
And in the following you can see the result:
Do you have any solution for move checkbox in its correct place? (I use pure jsf not primefaces or any more)
Thanks.

This behavior is as documented. Your attempt to fix this makes absolutely no sense. The <c:forEach><f:selectItem> should just be a <f:selectItems> and you should be using a custom renderer for the job. Tomahawk has already done it before for you, its <t:selectManyCheckbox> with layout="spread" attribute set, along with <t:checkbox> components declared at the desired places, allows you to control the markup fully:
<!-- This piece renders _nothing_. -->
<t:selectManyCheckbox id="foo" value="#{bean.selectedItems}" layout="spread">
<f:selectItems value="#{bean.availableItems}" />
</t:selectManyCheckbox>
<!-- You can markup those the way you want. They solely render <input>. -->
<t:checkbox for="foo" index="0" />
<t:checkbox for="foo" index="1" />
<t:checkbox for="foo" index="2" />
<t:checkbox for="foo" index="3" />
...
An alternative is to just fix your CSS styles. It look too much like that you overgeneralized table, tr, td, etc styles to be applied on all of those elements instead of only those by a specific style class such as table.datatable for <h:dataTable styleClass="datatable">.

Related

How to collapse or expand all RichFaces collapsiblePanel elements on the page?

I'm using RichFaces with JSF to develop a simple app. One page of this app contains several collapsiblePanel elements. Some of the collapsiblePanel elements are nested, but never more than a second layer.
I would like to provide links or buttons on the page to expand all and collapse all collapsiblePanel elements on the page. How can I do that?
The elements currently use the switchType="client" attribute to let the client handle the expanding and collapsing. I suspect that using a type of ajax instead may help, but I'm not sure nor do I know how I would take advantage of it.
Update: My question may be easier to understand if I include an example of what I'm trying to do:
<h:form>
<a4j:commandButton actionListener="#{bean.setDefaultExpanded(true)}"
render="reportPanel" value="Expand all" />
<a4j:commandButton actionListener="#{bean.setDefaultExpanded(false)}"
render="reportPanel" value="Collapse all" />
<h:panelGrid id="reportPanel">
<ui:repeat var="account" value="#{bean.results.entrySet().toArray()}">
<rich:collapsiblePanel expanded="#{bean.defaultExpanded}">
<ui:repeat var="chargeGroup" value="#{account.value.entrySet().toArray()}">
<rich:collapsiblePanel expanded="#{bean.defaultExpanded}">
<h:outputText value="content: #{chargeGroup.value}" />
</rich:collapsiblePanel>
</ui:repeat>
</rich:collapsiblePanel>
</ui:repeat>
</h:panelGrid>
</h:form>
The <rich:collapsiblePanel> has the expanded attribute, you can bind it to bean property and control the expansion from there. Something like this
<rich:collapsiblePanel id="panel1" expanded="#{bean.expanded}" …>
<a4j:commandButton actionListener="#{bean.togglePanels()}"
… render="panel1, panel2, …"/>
The switchType controls where the content is pulled from, not how you expand/collapse the panel.
I had the same problem when click individual panels and then expand/collapse all. This work for me (richfaces 4.2.3):
<h:commandButton immediate="true" action="#{controllerBean.toggleMin}" value="collapse all" >
<a4j:ajax render="panel1 panel2"></a4j:ajax>
</h:commandButton>
<h:commandButton immediate="true" action="#{controllerBean.toggleMax}" value="expand all">
<a4j:ajax render="panel1 panel2"></a4j:ajax>
</h:commandButton>
...
<rich:collapsiblePanel id="panel1" immediate="true" expanded="#{modelBean.expanded}" header="Title text" switchType="client">
...
</rich:collapsiblePanel>
...

using insertChildren AND getting child attributes

I am actually trying to create a custom composite table component because h:datatable or p:datatable do not fit my needs. Nevertheless it shall be used like a primefaces datatable.
After I found JSF composite component childrens
and
Expose items of a list while iterating within composite component I saw the finish line, but now I got stuck.
My xhtml:
<h:body>
<sm:datatable mode="columntoggle" id="mytable" value="#{managerBean.objects}" var="object">
<sm:column header="KeyHeader" property="key">
<h:outputText value="#{object.key}"/>
</sm:column>
<sm:column header="ValueHeader" property="value">
<h:outputText value="#{object.value}"/>
</sm:column>
</sm:datatable>
</h:body>
And this is the datatable composite:
<cc:interface>
<cc:attribute name="id" />
<cc:attribute name="mode" />
<cc:attribute name="var" />
<cc:attribute name="value" type="java.util.List"/>
</cc:interface>
<cc:implementation>
<table data-role="table" data-mode="#{cc.attrs.mode}" id="my-table">
<thead>
<tr>
<ui:repeat value="#{component.getCompositeComponentParent(component).children}" var="child">
<th>
<h:outputText value="#{child.attrs.header}"/>
</th>
</ui:repeat>
</tr>
</thead>
<tbody>
<ui:repeat value="#{cc.attrs.value}" var="object">
<tr>
<c:forEach items="#{cc.children}" var="child" varStatus="loop">
<cc:insertChildren/>
</c:forEach>
</tr>
</ui:repeat>
</tbody>
</table>
</cc:implementation>
And that's the column composite
<cc:interface>
<cc:attribute name="header" />
<cc:attribute name="property" />
<cc:facet name="content"/>
</cc:interface>
<cc:implementation>
<td><cc:insertChildren/></td>
</cc:implementation>
thead works standalone
tbody works standalone
Putting them together like above I only get tbody. thead always stays empty Any suggestions?
Thanks for your help in Advance!
This is not a bug, it actually works as designed in mojarra. Using cc:insertChildren moves the children to the parent tag of the cc:insertChildren tag. This problem is equivalent to another problem and has the same solution. See my answer to this question.
Basically, you put a <ui:fragment> around the <cc:insertChildren>, bind that fragment to a property in a FacesComponent bean.
#{cc.children} which is equivalent to
#{component.getCompositeComponentParent(component).children} should both work
but for some reason fail to work in some versions , I guess this part of JSF is still little buggy .
Have you tried
#{cc.getFacets().get('javax.faces.component.COMPOSITE_FACET_NAME').children}
Please refer this thread as well,
In JSF2, how to know if composite component has children?
I was having the same issue. My workaround was to use a renderFacet, instead of insertChildren.
To iterate over the inserted elements I have used: #{cc.facets.yourFacetName.children} and to insert the elements themselves I have used: <composite:renderFacet name="yourFacetName"/>.
I've found iterating over children and using <composite:insertChildren /> in the same component to be near impossible. At least in the Mojarra 2.2.6 implementation.
The intermediate facet approach did not work for me either.
Eventually, my solution was to:
retain the child component (tab) as is
remove all code from the composite:implementation of parent (tab group) component
implement encodeAll() in the the faces component corresponding to parent
This question is over a year old. Please share if there's a simpler solution in sight.

How display something near h:selectOneRadio item?

I have some list of elements, that generates my <h:selectOneRadio> items:
<h:selectOneRadio id="list#{cand.id}" value="#{mybean.value}" layout="pageDirection">
<c:forEach items="#{mybean.list}" var="c">
<f:selectItem id="first#{c.id}" itemlabel="#{c.surname}" itemValue="#{c.name}" />
</c:forEach>
</h:selectOneRadio>
I want next each element display <h:outputText> with value #{c.id}, so that at each row will be my radioButton element and next it some textbox. How can I do it ?
I tried something like that:
<h:selectOneRadio id="candidates1#{cand.id}" value="#{candidates.selectedCandidate1}" layout="pageDirection">
<c:forEach items="#{candidates.c1}" var="cand">
<td>
<f:selectItem id="first#{cand.id}" itemlabel="#{cand.surname}" itemValue="#{cand.name}">
<h:outputText id="c1ShortName#{cand.id}" value="#{cand.id}" />
</f:selectItem>
</td>
<td>
<h:outputText id="c1ShortName#{cand.id}" value="#{cand.id}" />
</td>
</c:forEach>
</h:selectOneRadio>
But it deisplays all radioButtons after last outputText.
I want something like the below screenshot. When right part is for example IDs, then it can be encrypted and decrypted.
Just put it in the item label.
itemlabel="#{c.id} #{c.surname}"
Or the other way round, you was not clear on that.
itemlabel="#{c.surname} #{c.id}"
You can if necessary use HTML like so, you should only beware of XSS attack hole in the surname.
itemlabel="#{c.surname} <strong>#{c.id}<strong>" itemEscaped="false"
Or, if you actually want to have them outside the generated <label>, then use a 3rd party component library. This is namely not supported by <h:selectOneRadio>. For example, Tomahawk's <t:selectOneRadio> has a layout="spread" attribute for that.
See also:
Radio buttons in different parts of the page
<h:selectOneRadio> renders table element, how to avoid this?
Unrelated to the concrete problem, you don't need that <c:forEach>. That's plain clumsy. Just use <f:selectItems var>. This is new since JSF 2.0, perhaps you were focusing too much on ancient JSF 1.x targeted resources.
<h:selectOneRadio ...>
<f:selectItems value="#{mybean.list}" var="c"
itemlabel="#{c.id} #{c.surname}" itemValue="#{c.name}" />
</h:selectOneRadio>
See also:
Our selectOneMenu wiki page

Issue in attribute for on h:outputLabel inside ui:repeat

I have following piece of code, i want to render radioButtons and labels for them. Due to the layout renderized by selectOneRadio and selectItem i decided to use plain HTML for the input radioButtons.
<h:panelGrid columns="6">
<ui:repeat value="#{myBean.list}" var="item">
<input id="#{item.innerList[0].id}" type="radio" name="radioItem" value="#{item.innerList[0].id}" />
<h:outputLabel for="#{item.innerList[0].id}" value="#{item.label}" />
</ui:repeat>
</h:panelGrid>
When trying to assign a label for them using outputLabel it renders the attribute for in HTML something like:
j_idt94:0:theidiassigned
The prependId flag in the tag form containing this code is set to false and in the documentation there is no such flag in the attributes of the other containing tags of the outputLabel.
The ui:repeat component is a NamingContainer. It controls the client identifier of its children.
The for attribute on a h:outputLabel will generally look for a component with a matching component identifier or client identifier.
So, for this markup:
<foo:someNamingContainer id="x">
<h:inputText id="foo" />
<h:outputLabel for="foo" />
</foo:someNamingContainer>
...the label would emit the matching, namespaced identifier <label for="...:x:foo".
There is no matching JSF component with a matching id since you are using a straight XHTML <input> element.
Consider just using a XHTML <label> element instead.

Custom selectItems

i want to customize selectItems
to display an image conditionally beside each checkbox
so first i tried to display the image for all checkboxes
but it gets displayed only once, here's what i tried:
<h:selectManyCheckbox value="#{myBean.checkboxesArry}" layout="pageDirection">
<f:selectItems value="#{myBean.mapOfCheckBoxes}" var="entry">
<label>
<ice:graphicImage url="/resources/images/myImage.bmp"/>
<b>#{entry.value}</b>
</label>
</f:selectItems>
</h:selectManyCheckbox>
please advise how to accomplish that ?
You cannot nest UI compnents in <f:selectItems> that way. I however see that you're using ICEfaces, you should then be able to use <ice:selectManyCheckbox layout="spread"> in combination with <ice:checkbox> instead.
<ice:selectManyCheckbox id="foo" value="#{myBean.checkboxesArry}" layout="spread">
<f:selectItems value="#{myBean.mapOfCheckBoxes}" />
</ice:selectManyCheckbox>
<c:forEach items="#{myBean.mapOfCheckBoxes}" var="entry" varStatus="loop">
<ice:checkbox for="foo" index="#{loop.index}" />
<ice:graphicImage url="/resources/images/myImage.bmp" />
<b>#{entry.value}</b>
</c:forEach>
(untested as I don't use ICEfaces, but the above construct works for Tomahawk, from which ICEfaces has basically copied the implementation; you can also use <ui:repeat> but it only supports Map since JSF 2.1)
See also:
Radio buttons in different parts of the page

Resources