Group visibility of rich:columns inside rich:datatable - jsf

I have a set of columns inside a rich:datatable, those columns are visible based on some preprocessed conditions. An example of what I want to do is this:
<rich:datatable value="tableList" var="list">
<h:panelGroup rendered="#{condition}">
<rich:column>
Component
<rich:column>
<rich:column>
Component
<rich:column>
</h:panelGroup>
<h:panelGroup rendered="#{not condition}">
<rich:column>
Component
</rich:column>
</h:panelGroup>
</rich:datatable>
The problem here is that the panelGroup tag never gets rendered inside the rich:datatable, even when I remove the "rendered" condition. I tried with an a4j:outputPanel and a few others but none worked.
I could remove the panel and put the condition in each column but that would be the last thing I would do.
Why is not working? Regards.

In fact, I am pretty sure that the <rich:dataTable> will ignore any direct children that are not a UIColumn or Column object (I just had a look on org.richfaces.component.ColumnsIterator, used by UIDataTable).
In others words, your <h:panelGroup> will simply be ignored by the <rich:dataTable>, not matter when the rendered attribute value is.
To solve your problem, I see three solutions:
Put a rendered attribute on each <rich:column>;
Use the <rich:columnGroup> component;
Define two <rich:dataTable>, one display when #{condition} is evaluated to true, the other one when it is false.

Related

selection issue p:dataTable with selectionmode set to multiple nested in p:dataGrid

I'm working on a PrimeFaces project, where I choose to use a p:DataTable inside a p:DataGrid. The DataTable has the selectionMode attribute set to "multiple". I have a button on the page and when I click on it, I want to get all the selected checkboxes inside the various generated tables. All the checkboxes bring the same type of information (they are in different tables because of an information grouping scheme I use in the project).
Since I have multiple DataTables in the final rendered page, how can I get the selected checkboxes? I tried using the selection="#{myBean.selectedOptions}" attribute of the DataTable, but it seems to get just one of the generated tables' selected options (aparently the first one). What can I do to get the selected options of all tables generated by the p:DataGrid? Javascript? Is there any point I'm missing in the DataTable behavior?
(Well.. I don`t know whether I was able to make myself clear enough - English is not my native language).
[edited]
More information:
The number o DataTables generated is variable
I tried using the jsf visit method to traverse the user interface component view as shown here, looking for all checkboxes inside the DataGrid, but it couldn't find any of the checkboxes (I printed out to the console all the elements found). I think it's because the checkboxes are encapsulated in DataTable component. This made me think about not using the selectionMode="multiple" and, instead, manually add the checkboxes and a hidden input element for each one so I can find the checkboxes (or the "input hidden") using the visit method. The sad part of this aproach is that I'd have to stop using some good stuff of the DataTable selectionMode="multiple" feature, like hilighting the row if the corresponding checkbox is checked, and the ready to use "check all" checkbox it automatically put in the header of the ckeckboxes column.
I tried using a nested List in the selection attribute, but it didn't work. The main idea was using something like selection="#{bean.myListOfLists.get(t.counter)}". The "counter" variable is taken from the very object that is used to fulfill the current row of the DataTable (represented by the t variable in the attribute var="t"). The DataTable seems to not accept this approach. It doesn`t fulfill the nested lists.
I tried using the above approch with a modification: instead of a list of lists, a build a new class "B" and made a list of B (selection="#{bean.myListOf_B_Objects.get(t.counter).listInsideBObject}"). The result is simliar to the last approach: none of the lists inside the B objects were fulfilled.
Below there is a simplified view of what I did (more similar to the last case, but it's just to get the big picture)
<p:dataGrid var="gridCellContent"
value="#{myBean.dataGridContent}"
layout="grid" id="id01" columns="3"">
<p:dataTable var="something"
value="#{gridCellContent.listOfSomething}"
rowKey="#{something.id}"
selection="#{myBean.listOf_B_Objects.get(gridCellContent.counter).listInside_B_Object}">
<p:column selectionMode="multiple" />
<p:column>
<h:outputText value="#{something.sometext}" />
</p:column>
</p:dataTable>
<f:facet name="footer">
<p:commandButton id="btnSave" value="Save"
actionListener="#{myBean.btnSave}"/>
</f:facet>
</p:dataGrid>
[edited 2] Following #JaqenH'ghar's sugestion I tried out the modifications below, which unfortunately still din't work:
<p:dataGrid var="gridCellContent"
value="#{myBean.dataGridContent}"
layout="grid" id="id01" columns="3"
rowIndexVar="count">
<p:dataTable var="something"
value="#{gridCellContent.listOfSomething}"
rowKey="#{something.id}"
selection="#{myBean.listOfLists.get(count)}">
<p:column selectionMode="multiple" />
<p:column>
<h:outputText value="#{something.sometext}" />
</p:column>
</p:dataTable>
<f:facet name="footer">
<p:commandButton id="btnSave" value="Save"
actionListener="#{myBean.btnSave}"/>
</f:facet>
</p:dataGrid>
And for myBean:
#ManagedBean
public class MyBean {
...
private List<List<Something>> listOfLists = new ArrayList<List<Something>>();
public List<List<Something>> getListOfLists(){
this.listOfLists.add(new ArrayList<Something>());
return this.listOfLists;
}
public void setListOfLists(List<Something> listOfSomething) {
this.listOfLists.add(listOfSomething);
}
...
}

h:dataTable renders rows correctly but does not show cell values while ui:repeat does

I have the following data table.
<h:dataTable value="#{flightReservation.flightList}" var="flight">
<h:column>
<h:outputText value="#{flight.fromPlace}" />
</h:column>
<h:column>
<h:outputText value="#{flight.toPlace}" />
</h:column>
</h:dataTable>
It does not show any data inside the cells, even though the number of rows is equal to the flightList size.
When I replace it by <ui:repeat>, then it shows the data.
<ui:repeat value="#{flightReservation.flightList}" var="value">
<h:outputText value="#{value.fromPlace}" />
<h:outputText value="#{value.toPlace}" />
</ui:repeat>
How is this caused and how can I solve it?
I encountered the same behaviour once and it was simply an issue with the scope of variables:
You are saying, that the number of rows is correct, but the content not displayed. You are naming the variable flight and I assume that a value with this name has been used earlier in your markup or even used as a <ui:param>.
The Datatable is now iterating (internal) and generating the correct amount of rows, but when it tries to access the properties of fligt jsf refers to the earlier declared variable and fails to find the properties fromPlace, toPLace etc.
Try to rename your variable and see if this solves your issue.
The example bellow would produce stringList.size() times yoloyolo even if one would expect the content of the list to be shown. And if the listsource is made out of objects, any instance access on the attributes will fail cause yoloylo is not an object of the expected type.
<ui:param name="foo" value="yoloyolo" />
<h:dataTable value="#{backingBean.stringList}" var="foo">
<h:column>
<f:facet name="header">string</f:facet>
- #{foo}
</h:column>
</h:dataTable>

Filtering issues (no change in contents) in datatable primefaces 3.5, sorting works

Primefaces 3.5 doesn't seem to filter data at all from the datatable, oddly enough it somehow reorders them as I type, so, there must be some AJAX calls firing, but obviously not the right ones.
<h:panelGroup id="table-wrapper-component">
<prime:dataTable
rendered="#{artifactSelectionBackingBean.visibleComps}"
value="#{artifactSelectionBackingBean.components}"
var="tagInfoObject" emptyMessage="No tags found with given criteria"
filteredValue="#{artifactSelectionBackingBean.filteredComponents}">
<prime:ajax event="filter" global="false" />
<prime:column sortBy="#{tagInfoObject.tagId}"
headerText="Identifier" filterMatchMode="contains" filterBy = "#{tagInfoObject.tagId}">
<h:outputText value="#{tagInfoObject.tagId}" />
</prime:column>
<prime:column sortBy="#{tagInfoObject.type.tagTypeId}"
headerText="Tag Identifier" filterMatchMode="contains" filterBy ="#{tagInfoObject.type.tagTypeId}">
<h:outputText value="#{tagInfoObject.type.tagTypeId}" />
</prime:column>
<prime:column sortBy="#{tagInfoObject.title}" headerText="Title" filterMatchMode="contains" filterBy="#{tagInfoObject.title}">
<h:outputText value="#{tagInfoObject.title}" />
</prime:column>
<prime:column filterBy="#{tagInfoObject.description}"
filterMatchMode="contains" sortBy="#{tagInfoObject.description}"
styleClass="wrap" headerText="Component Description">
<h:outputText value="#{tagInfoObject.description}" />
</prime:column>
</prime:dataTable>
</h:panelGroup>
Any help is appreciated! All the Beans and method calls exist and return the appropriate data, just that the filtering doesn't seem to work at all.
Also, note that sorting functions properly only filtering does not!
The issue was that you always need to wrap any filtering/sorting attributes in a data table with an h:form tag. This is not explicitly specified in the documentation of PrimeFaces, however, it is in the showcase here. I wrapped the whole thing in form tags.
So, don't forget to wrap your data tables in a form if you want any type of interaction provided by primefaces.
Your managed Bean Code will do a lot of good
Post your managed bean code.
May be you have not set the value for artifactSelectionBackingBean.filteredComponents in the managed bean

input binding in ui:repeat in jsf

i am using facelets jsf 2.0 with primefaces 3.0.M2 component library.
i am trying to achieve dynamic numbers of rows including iput fields that are filled when a datatable selection occurs.
whenever a selection is made the dynamic rows generated correctly with input fields but after the first selection for following selections dynamic row count changes correctly but the input fields does not update and keeps showing inputs from the first selection.
here is how i iterate list in facelet;
<ui:repeat value="#{goalEntranceBean.selectedCard.parameterList}" var="prmBean" >
<li><h:outputText value="#{prmBean.lookUp.value}"/></li>
<li>
<h:outputText value="Weight:"/>
<p:inputText id="wx" required="true" value="#{prmBean.weight}">
</p:inputText>
<h:outputText value="Percent:"/>
<p:inputText required="true" value="#{prmBean.percent}">
</p:inputText>
</li>
</ui:repeat>
my bean where i get the list of cards and set the selectedCard with rowSelect event in datatable.
#ManagedBean(name = "goalEntranceBean")
#ViewScoped
public class GoalEntranceAction implements Serializable {
private List<ScoreCard> personalCards = new ArrayList<ScoreCard>();
private ScoreCard selectedCard = new ScoreCard();
......
}
when i checked in debug mode i can see the true list but in screen the elements does not change.
This is a common problem (gets asked every couple of days). To make long story short, inputs inside ui:repeat do not work, period.
It is a problem with JSF, a long standing, famous one. Maybe it will be fixed. Maybe not, it seems that no one really cares (I mean - an input? in a... ui:repeat? such crazy scenario!).
A quick-fix is to use a h:dataTable, possibly ungodly abused with css to make it look like a list. A long-fix is to use some iterator from a different library. Primefaces has an element that should work that renders an unordered list.
thanks for your replies. Sorry for forget sharing the solution.
As i mentioned above i have primefaces datatable.
On row selection event i render datatable and want to update the cells of that datatable.
USING p:inputtext easily solved my problem. Now i can change the data on screen and i can see the values after update operation on screen. I don't understand the reason but it works.
<p:dataTable var="orgPrmBean"
value="#{scoreCardOperationsBean.selectedCard.orgParameterList}"
emptyMessage="#{labels.norecord}"
rowKey="#{orgPrmBean.id}"
>
<p:columnGroup type="header">
<p:row>
<p:column headerText="Parameters" colspan="3" style="text-align:left;width:480;"/>
</p:row>
</p:columnGroup>
<p:column style="text-align:left;width:200px;">
<h:outputText value="#{orgPrmBean.info}"/>
</p:column>
<p:column style="text-align:left;width:180px;">
<p:inputText value="#{orgPrmBean.weight}"
rendered="#{scoreCardOperationsBean.selectedCard.goalEdit}">
<f:convertNumber maxFractionDigits="0"/>
</p:inputText>
</p:column>
</p:dataTable>
It IS possible to make it work, but the solution is to bind the inputs to a backing bean, and update the values of the controls in the backing bean via listeners (using the new value received in the argument). Obviously this isn't a good solution if you have a complex form, as you need to add a listener/control in the backing bean for each control in the page, but it's practical if you just have one or two inputs.

JSF h:column tag not evaluating rendered attribute

I've got a JSF data table that conditionally displays each item based on a Boolean property of the item, as follows:
<h:dataTable value='#{sessionBean.items}' var='item'>
<h:column rendered='#{item.visible}'>
<h:outputText value='#{item.description}'/>
</h:column>
</h:dataTable>
My problem is that the rendered attribute does not seem to be referring to visible property in my item at all. I've put a tracing message in the getter for the property, and can confirm that the getter is not getting called at all. What really puzzles me though, is that the following works:
<h:dataTable value='#{sessionBean.items}' var='item'>
<h:column rendered='true'>
<h:outputText value='visible = #{item.visible}'/>
<h:outputText value='#{item.description}'/>
</h:column>
</h:dataTable>
That is, in this case all items are rendered, and the text "visible = true" or "visible = false" is successfully output for each. It is only in the column rendered attribute that the getter is not working.
Does anyone have any idea what might cause this behaviour, and what I should do to correct it?
Table columns (read: <td> elements which are all in the same column, which thus applies on all rows) cannot be rendered on a per-row basis. That's not really a JSF restriction, but more a HTML restriction. Ask yourself, how should the HTML end up to look like? What should the browser do with all those missing <td> elements on a per-row basis? Right, it makes no sense at all :)
Just move the row-based rendering to the cell contents:
<h:column>
<h:outputText value="#{item.description}" rendered="#{item.visible}"/>
</h:column>
Or make it a bean based rendering if you actually want to hide the whole column altogether:
<h:column rendered="#{sessionBean.visible}">
<h:outputText value="#{item.description}"/>
</h:column>

Resources