How display something near h:selectOneRadio item? - jsf

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

Related

Dynamic 2D arrayList table not working after refreshing in primefaces?

I am using prime-faces 5 and jsf, I've created dynamic 2D arraylist table based on Tester and Date, first time its showing values correctly with date. But next time onwards its showing different tester name in single row.
The above showing first row correctly showing tester name but 2nd and 3rd showing different values. But i want to display same tester name in each row level.
MY XHTML:
<div align="left" class="width100">
<div class="DTHeader">
<h:form id="frmres">
<h:panelGrid columns="2"
style="padding-top:35px;padding-left:30px;">
<h:outputText class="lighttxt1" value="Schedule Date" />
<p:calendar id="button" value="#{schedulerbean.sch.scheDate}"
styleClass="cal schdate" label="Schedule Date" showOn="button"
pattern="dd/MM/yyyy HH:mm" showButtonPanel="true"
required="true">
</p:calendar>
<h:outputText value="TCU Goal" class="lighttxt1" />
<h:panelGrid columns="1" >
<p:inputText id="tcu" label="The Value given in TCU is"
style="border: 1px solid #A8A8A8 !important;background: transparent !important;"
styleClass="txtbig" value="#{schedulerbean.sch.tcu}"
keypadOnly="true" required="#{tcselectionbean.mancnt} != 0}" />
<h:outputText value="(Total Tcu:#{schedulerbean.tottalTCU})" class="lighttxt1" />
</h:panelGrid>
<h:outputText value="Select Squad" styleClass="txtblack14" />
<p:selectOneMenu value="#{schedulerbean.sch.squadparam}"
panelStyleClass="panel" styleClass="DTDD ddwidth1">
<f:selectItem itemLabel="All Tester" itemValue=""
styleClass="txtblack14" />
<f:selectItems value="#{schedulerbean.squadLst}" var="squadval"
itemLabel="#{squadval}" itemValue="#{squadval}"
styleClass="txtblack14" />
</p:selectOneMenu>
</h:panelGrid>
<h:panelGrid columns="1">
<p:commandButton
actionListener="#{schedulerbean.resourcePlanWithPossibleEnddate}"
value="Calculate" styleClass="blubtn"
update=":frmres:reservtable" />
<h:panelGroup id="reservtable">
<table class="bor bortd" style="margin-left:32px;">
<thead>
<tr>
<th>Tester Name / Dates</th>
<c:forEach var="resdate" items="#{schedulerbean.resDateList}">
<th>#{resdate}</th>
</c:forEach>
</tr>
</thead>
<c:forEach var="reserv" items="#{schedulerbean.resList}">
<tr>
<td>
<h:selectBooleanCheckbox value="#{schedulerbean.testerCheckboxmap[reserv.testerName]}"
styleClass="lighttxt1" />#{reserv.testerName}</td>
<c:forEach var="resdate1" items="#{schedulerbean.resDateList}">
<td class='c#{reserv.reserveType.get(resdate1)}'>
#{reserv.testerName} #{reserv.tcuMap.get(resdate1)}</td>
</c:forEach>
</tr>
</c:forEach>
</table>
</h:panelGroup></h:panelGrid>
<p:commandLink styleClass="bluelinknew"
action="#{schedulerbean.setSchedulestep('step3')}"
update=":schmenufrm" value="Next" style="float:right;"
onclick="javascript:changets('schedule');" />
</h:form>
</div>
</div>
How can i achieve this?
You are misusing the forEach JSTL tag. The tag is only in effect when the component tree is built, and the component tree is not re-built for post-backs and AJAX requests.
bwright's suggestion to use a <p:dataTable> is good, but you could also use <ui:repeat> if you don't want to render an HTML table.
https://rogerkeays.com/jsf-c-foreach-vs-ui-repeat
The most important thing to understand about the JSTL tags in JSF is
that they do not represent components and never become a part of the
component tree once the view has been built. Rather, they are tags
which are actually responsible for building the tree in the first
place. Once they have done their job they expire, are no more, cease
to be, etc etc.
...
When is the view built?
Now that you understand that tag handlers are only effective when the
tree is built, the next logical question should be well, when is tree
built?
The short answer is that a new view is built for every request which
is not a postback. During a postback, the view is reconstructed from
saved state. Quite confusing, and not very obvious I know, but there
you have it.
...
My list doesn't change size after deleting or adding an item
When your view was built you only had, say, 5 items. If you post back
to this view and add or delete an item, your view still has 5
h:outputText components in it since it was restored from saved state.
In this simple case, you should use ui:repeat and your tree will
always contain one h:ouputText component which is iterated over with
differing values of ${item}.
If you rely on using c:forEach to dynamically include different form
components you could run into difficulty. Always try to think about
what the resulting tree looks like and remember it doesn't change on a
postback.
See also
https://rogerkeays.com/jsf-c-foreach-vs-ui-repeat (quoted above)
JSTL in JSF2 Facelets... makes sense?

Many SelectOneMenuRadio in a forEach [duplicate]

This question already has an answer here:
input component inside ui:repeat, how to save submitted values
(1 answer)
Closed 7 years ago.
I have a bean called Question with a lot of alternatives -->
Question have 1:N Alternative.
I have a Page with a lot of Question, like:
Page have 1:N Question
I need create a XHTML page showing the amount of questions and your alternatives, like this:
<c:forEach var="questaoCurso"
items="#{cursandoMB.paginaAtualProva.questoesCurso}">
<h:outputText value="#{questaoCurso.questao.texto}" />
<br />
<h:selectOneRadio style="font-weight: normal"
value="#{cursandoMB.alternativasEscolhida}" layout="pageDirection">
<f:selectItems value="#{questaoCurso.questao.alternativasPreenchidas}"
var="c"
itemValue="#{c}"
itemLabel="#{c.texto}" />
</h:selectOneRadio>
<br />
<br />
</c:forEach>
The problem is that I don't know how I can set each choose alternative in a List in my ManagedBean. I can't create one variable for each Question, because this is dynamic and I don't know the amount of questions in design-time.
SOLVED:
I used a Map in RadioButton, see:
<h:selectOneRadio
value="#{cursandoMB.alternativasEscolhidas[questaoCurso]}" converter="entityConverter" layout="pageDirection">
<f:selectItems
value="#{questaoCurso.questao.alternativasPreenchidas}" var="c"
itemValue="#{c}" itemLabel="#{c.texto}" />
</h:selectOneRadio>
First, You must not mix render-time (e.g. f:selectItems, h:inputText ...) and build-time tags (JSTL tags, f:actionListener, ui:include ... ), for more understanding of the view build time and render time concepts and how that works please take a look to this BalusC's answer: JSTL in JSF2 Facelets... makes sense?
So IMO the only thing to replace is the c:forEach tag with ui:repeat like this:
<ui:repeat var="questaoCurso"
value="#{cursandoMB.paginaAtualProva.questoesCurso}">
<h:outputText value="#{questaoCurso.questao.texto}" />
<br />
<h:selectOneRadio style="font-weight: normal"
value="#{cursandoMB.alternativasEscolhida}" layout="pageDirection">
<f:selectItems value="#{questaoCurso.questao.alternativasPreenchidas}"
var="c"
itemValue="#{c}"
itemLabel="#{c.texto}" />
</h:selectOneRadio>
<br />
<br />
</ui:repeat>
The value attribute of ui:repeat Tag is:
The name of a collection of items that this tag iterates over. The
collection may be a List, array, java.sql.ResultSet, or an individual
java Object. If the collection is null, this tag does nothing.
So you can use a List of Object in that value which in your case will be a List of Question objects, and in your Question bean you can include a List of answers (while Answer may also be a bean).

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

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

ValueChangeListener problem

While calling the ValueChangeListener in JSF based on value change in dropdown, it is calling all the ValueChangeListner that are on that page.
There are two valueChangeListener in DataTable, while changing value in one dropdwon the 2nd one also executing.
<t:column id="avlId" styleClass="coltextcenteralign">
<f:facet name="header">
<h:panelGroup>
<h:outputText value="#{bundle['travelLocalAccommodation.title.availability']}" />
<h:outputText value="*" style="color:red" />
</h:panelGroup>
</f:facet>
<t:selectOneMenu value="#{accomDtls.availability}" immediate="true"
valueChangeListener="#{TravelProcessingBB.localAccommodationBB.setAvailableFlag}" forceid="true" id="avl"
onchange="return availabilityAlert('#{accomDtls.prepopulatedFlag}','avl[#{table_count}]')"
styleClass="dropDownStyle" style="width:50">
<f:selectItem itemValue="Y" itemLabel="Yes" />
<f:selectItem itemValue="N" itemLabel="No" />
</t:selectOneMenu>
</t:column>
The value change alone won't automatically call the valueChangeListener. You need to submit the form as well. A commonly used "hack" is to call form.submit() using JavaScript during the onchange event. This will however submit the entire form. Truly the valueChangeListener will be triggered for all changed fields of the form.
To fix this in JSF 1.x, you need to hassle somewhat with the immediate attribute to skip all other form components from validating and with component binding so that you can properly get/set the other component's value. Long story short, I ever wrote an article about that: populate child menus in JSF 1.2.
In JSF 2.0, this is however easier to achieve with help of <f:ajax> tag. If you're really using JSF 2.0 (your current question doesn't indicate that), then let me know if you need an example.

Resources