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

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?

Related

How to hide a jsf element when page is loading

I am new to JSF and doing some sample login application. I need username,password only with tooltips.
I have added below extra jsf element rich:toolTip element added as below and my question is, how to hide this extra element.
I want to hide this element without removing from jsp.
When I inspected the source code from browser, UI is getting broken and added some extra space.
sample.jsp
<h:panelGrid>
<h:outputText value="username"/>
<h:inputText value="username">
<rich:toolTip value="enter uname" event="onmouseover"
direction="bottom-right" layout="block"/>
</h:inputText>
<h:outputText value="password"/>
<h:inputText value="password">
<rich:toolTip value="enter password" event="onmouseover"
direction="bottom-right" layout="block"/>
</h:inputText>
<rich:toolTip value="how to hide this element" event="onmouseover"
direction="bottom-right" layout="block"/>
</h:panelGrid>
Could anyone help on this?

Dynamically adding components in multiple columns & legend creation [duplicate]

I'm working on dashboard application where I have to retrieve a set of records and display in dynamic tables boxes. Page frame length is fixed. now of columns and rows can be initialized. It should look like this sample:
Currently I'm using data table to display but it prints all the data in one column. How would I change my code to above pattern?
<o:dataTable id="tabBlSearch" var="item"
onkeyup="handleLeftRightArrowOnDataTable('frmDashBoard:tabBlSearch')"
value="#{bLDashBoardAction.listBondLoc}">
<o:column style="width: 20px;">
<h:outputText value="#{item.awb}" />
</o:column>
</o:dataTable>
You can achieve this with standard JSF components using a <h:panelGrid> wherein <c:forEach> is been used to generate the cells during the view build time. The <ui:repeat> won't work as that runs during view render time.
<h:panelGrid columns="5">
<c:forEach items="#{bean.items}" var="item">
<h:panelGroup>
<h:outputText value="#{item.value}" />
</h:panelGroup>
</c:forEach>
</h:panelGrid>
As to component libraries, I don't see anything in OpenFaces' showcase, but PrimeFaces has a <p:dataGrid> for exactly this purpose, even with pagination support.
<p:dataGrid columns="5" value="#{bean.items}" var="item">
<p:column>
<h:outputText value="#{item.value}" />
</p:column>
</p:dataGrid>

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

How do I conditionally render an <f:facet>?

I would like to be able to conditionally omit a footer from a PrimeFaces panel element:
<p:panel header="some text">
<f:facet name="footer">
#{message}
</f:facet>
<!-- ... -->
</p:panel>
I hoped that the rendered attribute would work:
<p:panel header="some text">
<f:facet name="footer" rendered="#{!empty message}">
#{message}
</f:facet>
<!-- ... -->
</p:panel>
But the footer is still rendered, with empty content. It appears that facet does not have the rendered attribute: http://www.jsftoolbox.com/documentation/help/12-TagReference/core/f_facet.html.
What's the right way to do this?
I was able to solve this by swapping the facet out for an attribute. To summarize:
This works
<p:panel ...>
<f:attribute name="footer" value="#{message}"/>
<!-- ... -->
</p:panel>
But this doesn't work
<p:panel footer="#{message}">
<!-- ... -->
</p:panel>
Neither does this
<p:panel ...>
<f:facet name="footer">#{message}</f:facet>
<!-- ... -->
</p:panel>
Nor this
<p:panel ...>
<f:facet name="footer">
<h:outputText value="#{message}" rendered="#{!empty message}"/>
</f:facet>
<!-- ... -->
</p:panel>
by "works" I mean:
"renders no footer — not just an empty footer — when #{message} is empty or null; otherwise, correctly renders the footer with the specified text."
PrimeFaces forum thread on this issue
You could declare a ui:param and let the template check the param while renderring.
The facet in the template could then be declared as:
<f:facet name="#{hideFooter == null or not hideFooter ? 'footer' : ''}">
#{message}
</f:facet>
Any page can then declare this param
<ui:param name='hideFooter' value='#{some rule}' />
and set the appropriate rule for the param. For any page that does not declare the param, the footer will be displayed.
Here's what I did in trying to conditionally render a facet within a composite component.
<composite:interface>
<composite:facet name="header" required="false" />
</composite:interface>
<composite:implementation>
<p:panel>
<c:if test="#{empty component.facets.header}" >
<f:facet id="#{cc.attrs.id}_default_header" name="header">
all sorts of stuff here
</f:facet>
</c:if>
<c:if test="#{not empty component.facets.header}">
<composite:insertFacet id="#{cc.attrs.id}_custom_header" name="header" />
</c:if>
<composite:insertChildren id="#{cc.attrs.id}_content"/>
</p:panel>
</composite:implementation>
This let's the user of the composite component supply the header facet if they want, and if they don't, we supply a default. Obviously, instead of providing a default, you could simply not do anything.
This mixes c:if in jsf controls, but we didn't see any adverse effects.
I have come across a similar issue with plain JSF. I am not sure how a <p:panel> is rendered, but if it is rendered as a table, you can try this:
First, declare a CSS-class like this:
.HideFooter tfoot {
display: none;
}
Then set that class conditionally on the panel:
<p:panel styleClass="#{renderFooterCondition ? null : 'HideFooter'}">
The footer is still rendered in the JSF-sense, but it is not displayed and does not take up any space in the page when viewed by the user-agent.
I successfully solved this problem using ui:fragment
<ui:fragment rendered="...Test...">
<f:facet name="footer">
...
</f:facet>
</ui:fragment>
works for example to conditionnaly render the footer of a primefaces datatable (the rendered attribute of the facet does not work).
Not sure how well this would work for your footer, but I had the same issue with a legend I was trying to conditionally render. I fixed it by using the rendered on anything inside the facet tag.
<p:fieldset>
<f:facet name="legend">
<h:outputText value="#{header1}" rendered="#{header1.exists}"/>
<h:outputText value="#{header2}" rendered="#{not header1.exists}"/>
</f:facet>
content
</p:fieldset>
I had difficulty trying c:if with my ui:repeat, so this was my solution. Not quite the same as your problem, but similar.
Facets are not intended to render HTML, which is why it doesn't have the rendered attribute. Facets add functionality to a page. The term facet is probably a poor choice of name. It's very ambiguous.
..if the list compiled by ITworld's Phil Johnson has it right, the
single hardest thing developers do is name things.
ie.
JSF facets
A project facet is a specific unit of functionality that you can add to a project when that functionality is required. When a project facet is added to a project, it can add natures, builders, classpath entries, and resources to a project, depending on the characteristics of the particular project. JSF facets define the characteristics of your JSF enabled web application. The JSF facets specify the requirements and constraints that apply to your JSF project.
The JSF facets supply a set behaviors and capabilities to your web application.
This is a counter-answer to the answer from Ludovic Pénet.
This worked for me in <f:facet name="footer"> in selected p:column items of a p:dataTable (Primefaces 5.3):
...
Note how I have the ui:fragment inside the f:facet, not outside (not wrapping) it. It definitely completely removes the entire row when every footer facet is tested to NOT render (as far as I can tell, independent of the content within the ui:fragment).
Try with this, from primefaces web page
<p:columnGroup type="footer">
<p:row>
<p:column colspan="3" style="text-align:right" footerText="Totals:" />
<p:column footerText="your value in ajax" />
<p:column footerText="your value in ajax" />
</p:row>
</p:columnGroup>
clik here, to view primefaces' webpage
For those who landed here trying to hide the footer, instead of header, but the syntax component.facets.footer didn't work, should try this:
<p:panel id="panelContent">
<c:if test="#{not empty cc.facets.footer}">
<f:facet name="footer" height="100%">
your content
</f:facet>
</c:if>
</panel>
Why don't you enclose the content of the footer into a panelGroup which has the rendered attribute?
This way:
<p:panel header="some text">
<f:facet name="footer">
<h:panelGroup rendered="#{!empty message}">
#{message}
</h:panelGroup>
</f:facet>
<!-- ... -->
</p:panel>
I do it in my weapp and it works, no footer is rendered.
I don't use primefaces though, I do it with h:datatable, but I think that it must works with p:panel too.
I try this solution and ok. (http://www.coderanch.com/t/431222/JSF/java/dynamically-set-panel-header-condition)
<rich:dataGrid value="#{myMB.student.list}" rendered="#{!empty myMB.student and !empty myMB.student.list}" var="st" rowKeyVar="row">
<rich:panel>
<f:facet name="header">
<h:panelGroup id="panelHeader">
<h:outputText value="Just one student" id="header1" required="true" rendered="#{!myMB.manyStudents}"/>
<h:outputText value="#{row+1}º Student" id="header2" required="true" rendered="#{myMB.manyStudents}"/>
</h:panelGroup>
</f:facet>
<rich:panel>

Absolute reRendering using RichFaces

My problem is that RichFaces reRender does not work 'under' the current element in the element tree; only upper elements get rerendered.
Is there any way to access lower elements with AJAX?
Any help would be appreciated!
Daniel
EDIT I edited this question to a more general one. See revisions if interested in the original question.
reRender works with providing an the id of the target object you want to reRender (inside the same naming container - form most often)
the id should be a unique string, according to html spec
reRender allows dynamic value - i.e. reRender="#{myBean.currentItemsToRerender}
Based on that I think you should be able to achieve what you want (although it's not entirely clear)
Update:
UIComponent.findComponent(..) has a well-defined algorithm for resolving ids. So for absolute referencing your reRendered id should start with : and then continue through the hierarchy of the naming containers.
Here is an example where changePanel111() changes the content of a lower element:
<h:form id="form" prependId="true">
<rich:panel id="PANEL1">
<h:outputText id="PANEL1TEXT" value="#{ajaxTestBean.panel1}"/>
<rich:panel id="PANEL11">
<h:outputText id="PANEL11TEXT" value="#{ajaxTestBean.panel11}"/>
<rich:panel id="PANEL111">
<h:outputText id="PANEL111TEXT" value="#{ajaxTestBean.panel111}"/>
</rich:panel>
</rich:panel>
<rich:panel id="PANEL12">
<h:outputText id="PANEL12TEXT" value="#{ajaxTestBean.panel12}"/>
<br/>
<a4j:commandLink value="CHANGE PANEL12" action="#{ajaxTestBean.changePanel12}">
<a4j:support reRender="PANEL12" event="onclick"/>
</a4j:commandLink>
<br/>
<a4j:commandLink value="CHANGE PANEL111" action="#{ajaxTestBean.changePanel111}">
<a4j:support reRender="form:PANEL111" event="onclick"/>
</a4j:commandLink>
</rich:panel>
</rich:panel>
</h:form>
Notice how the lower element needs to be identified as form:PANEL111.
Hope this helps!
reRender can point to any component outside the form as well. For example this works:
<h:form>
<a4j:commandButton reRender="panel"/>
</h:form>
<h:panelGrid id="panel">
...
</h:panelGrid>
For my MyFaces+Richfaces App, <rich:panel> tag was not working as described in the selected answer. When I changed it to <a4j:outputPanel ajaxRendered="true" />, it started working as given here "<a4j:commandLink> Not Rerendering"
Configuration: MyFaces 2.1.10(Facelets used for templating) and Richfaces 4.2.3.
Hope this will help.

Resources