I am trying to select/unselect all checkboxes in the datatable using a single checkbox. As I am trying to set it on the server, I am unable to do so. I have looked around for solutions but could not get how to accomplish on the server side.
Here is the code.
xhtml file###
<rich:column styleClass="center-aligned-text">
<f:facet name="header">
<h:selectBooleanCheckbox id="selectAll" title="selectAll" valueChangeListener="#{workspace.selectAllComponents}">
<a4j:support event="onclick" reRender="listcomponents"/>
</h:selectBooleanCheckbox>
</f:facet>
<h:selectBooleanCheckbox id="selectComponent"
value="#{workspace.selectedComponentIds[componentInfo.id]}">
</h:selectBooleanCheckbox>
</rich:column>
Java File
// Select All and delete
public void selectAllComponents(ValueChangeEvent event){
// If the check all button is checked, set all the checkboxes as selected
if(!selectAll)
{
changeMap(selectedComponentIds,true);
setSelectAll(true);
}
else // If the button is unchecked, unselect all the checkboxes
{
changeMap(selectedComponentIds,false);
setSelectAll(false);
}
}
public void changeMap(Map<Long,Boolean> selectedComponentMap, Boolean blnValue){
if(selectedComponentMap != null){
Iterator<Long> itr = selectedComponentMap.keySet().iterator();
while(itr.hasNext()){
selectedComponentMap.put(itr.next(), blnValue);
}
setSelectedComponentIds(selectedComponentMap);
}
}
I am marking all the values in the list as true when the checkbox is checked and false when unchecked.
But the page doesn't reload the data properly.
Is my method to approach to the problem correct? Or is there a efficient alternative?
It's because the ValueChangeEvent occurs before the update model phase, so the value you change gets overwritten.
Do this in the public void selectAllComponents(ValueChangeEvent event)
if (event.getPhase() != PhaseId.INVOKE_APPLICATION) {
event.setPhase(PhaseId.INVOKE_APPLICATON);
event.queue();
} else {
//do your stuff here
}
Or just before your code add next line code in your original method
selectAll = (Boolean) event.getNewValue();
Related
I am working with Primefaces DataTable component. The user makes some city-district-service type choices before hitting the button and the datatable gets filled with the needed urban services (hospital, schools etc.), located at the needed spots of the city. The below code contains only the fetching button and the table itself.
When you fetch the first results you want, there isn't any problem. All is good, paginator works well. The problem starts when you filter the results by name. They actually get filtered very well too, BUT after a filtering is done; if you make other choices about the city, district or service and try fetching them; the columns of datatable gets filled with '| 0 | (empty) | (empty) |' rows (I guess its because the ID column is of type int and the other two are strings). Additional info: the number of the newly created empty rows are exactly equal to the former filter results.
I made the necessary debugging and found that at the backend everything is perfect. I get all my fetched objects. Actually when I type anything in the filter bar the new results become exposed too. It seems to be a problem totally in the client side rendering, though I couldn't find a way to solve it.
Any help would be greatly appreciated.
Update: After working on it for several more hours, I concluded that the reason might not be the filter but the paginator. Because when I turn off the paginator and get a full scrollable table, everything works perfectly well. Still not sure about the exact reason, so I edited the question subject according to that.
p.s: I'm using Primefaces 5.3, JSF 2.2 Mojarra, JDK 1.7, TomEE Plume
<p:commandButton action="#{filterByLocation.fetchServicesByLocation}" id="elbuton" value="Fetch" icon="ui-icon-check" onclick="PF('servisWidget').clearFilters();" update="servisList" />
<p:dataTable id="servisList" paginator="true" paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}" rowsPerPageTemplate="5,10,15" rows="10" var="loc" value="#{filterByLocation.finalResults}"
widgetVar="servisWidget">
<p:column headerText="ID">
<h:outputText value="#{loc.id}" />
</p:column>
<p:column headerText="NAME" filterBy="#{loc.name}" filterFunction="#{filterByLocation.filterResults}">
<h:outputText value="#{loc.name}" />
</p:column>
<p:column headerText="SERVICE NAME">
<h:outputText value="#{loc.serviceName}" />
</p:column>
</p:dataTable>
My backing bean (getters/setters excluded for clarity):
#ManagedBean
#ViewScoped
public class FilterByLocation {
private List<LocationEntity> cities;
private List<LocationEntity> districtSelection;
private List<LocationEntity> finalResults = new ArrayList<LocationEntity>();
private List<Integer> selectedNodes = new ArrayList<Integer>();
private String filterText;
private String filterName;
private int city;
private int district;
public FilterByLocation() {
setCities(LocationTreeDAO.fetchCities());
}
public void listDistricts() {
setDistrictSelection(LocationTreeDAO.fetchDistricts(city));
}
public void selectNode(NodeSelectEvent node) {
TreeNode treeNode = node.getTreeNode();
LayerEntity layer = (LayerEntity) treeNode.getData();
selectedNodes.add(Integer.valueOf(layer.getId()));
}
public void unselectNode(NodeUnselectEvent node) {
TreeNode treeNode = node.getTreeNode();
LayerEntity layer = (LayerEntity) treeNode.getData();
selectedNodes.remove(Integer.valueOf(layer.getId()));
}
public void fetchServicesByLocation() {
setFinalResults(LocationTreeDAO.fetchFilteredServices(getCity(), getDistrict(), getSelectedNodes(), getFinalResults()));
setFilterText("");
}
public boolean filterResults(Object value, Object filter, Locale locale) {
setFilterText((filter == null) ? null : filter.toString().trim());
if (filterText == null || filterText.equals("")) {
return true;
}
if (value == null) {
return false;
}
String searched = value.toString().toUpperCase();
filterText = filterText.toUpperCase();
if (searched.contains(filterText)) {
return true;
} else {
return false;
}
}
Two screenshots depicting the situation
before
after
The filterFunction parameter of
<p:column ... filterFunction="#{filterByLocation.filterResults}" ...> is not necessary.
Change the statement to
<p:column headerText="NAME" filterBy="#{loc.name}" filterMatchMode="contains">
Add a List for the filtered values
<p:dataTable ... filteredValue="#{filterByLocation.filteredResults} ...>
#ManagedBean
#ViewScoped
public class FilterByLocation {
...
private List<LocationEntity> filteredResults;
...
}
I have one dataTable in my screen. In the column header there is a selectBooleanCheckBox. If I
select it then all the boolean check boxes are get selected and deselected if I deselect the header boolean check box. My datatable is binded is with htmlDatatable. In bean all values are being set but it is not reflected in UI. Kindly help....
<t:dataTable id="physicalAccessDetailsDataTable1" binding="#{bean.htmlDataTable}">
<f:facet name="header">
<h:selectBooleanCheckbox id="selectAll" value="#{bean.editablePhysical}"
valueChangeListener="#{bean.selectAllFromPhysicalDatatable}"
onclick="submit()" />
</f:facet>
here is my bean code...
public String selectAllFromPhysicalDatatable(ValueChangeEvent vcep) {
if (editablePhysical == false) {
System.out.println(editablePhysical);
editablePhysical = true;
for (PhysicalAccessDetail physicalAccessDetail : physicalAccessDetailsList) {
System.out.println("INside loop of true");
physicalAccessDetail.setEditable(true);
}
} else {
editablePhysical = false;
for (PhysicalAccessDetail physicalAccessDetail : physicalAccessDetailsList) {
physicalAccessDetail.setEditable(false);
}
}
return null;
}
I'm using t:dataScroller to scroll some data from a t:dataTable and it is working fine except for one thing: every time an action that causes the screen to be refreshed is triggered the t:dataScroller's index is set to 1.
To be more clear: when i'm in the second page (index == 2) and a screen refreshing action triggers, after the refresh, the data of the dataTable is still from index 2 but the dataScroller shows that the page being displayed is the first one.
I'm using the dataScroller this way:
<t:dataScroller for="myDataTable" id="myDataScroller" paginator="true"
paginatorMaxPages="#{myBean.paginatorMxPgs}"
pageCountVar="pgCount" pageIndexVar="#{myBean.curPg}"
actionListener="#{myBean.pgListener}">
<f:facet name="prv">
<h:panelGroup rendered="#{myBean.curPg > 1}" />
</f:facet>
<f:facet name="nxt">
<h:panelGroup rendered="#{myBean.curPg != pgCount}"/>
</f:facet>
</t:dataScroller>
i'm using tomahawk20-1.1.11.jar and myfaces-api-2.0.4.jar
For setting scroller to firstpage set actionlistener on submit button.
<t:commandButton actionListener="#{IFussBean.resetDataScroller}"
action="#{IFussBean.searchLocation}"
image="images/submit-button.png">
</t:commandButton>
Binding:
if it is datatable
<t:dataTable id="data"
headerClass=""
footerClass=""
rowClasses="text_holder"
columnClasses="search_img,search_txt"
var="item"
value="#{IFussBean.searchVideoList}"
preserveDataModel="false"
rows= "6"
binding="#{IFussBean.iFussData}"
>
Declare HtmlDataTable in your Bean,define its setter getter as below:
private HtmlDataTable iFussData;
Getter and setter
public HtmlDataTable getiFussData() {
return iFussData;
}
public void setiFussData(HtmlDataTable iFussData) {
this.iFussData = iFussData;
}
Now define ActionListener Method in Bean:
public void resetDataScroller(ActionEvent e) {
if(iFussData!= null) {
iFussData.setFirst(0);
}
}
Your page will set to first page when you'll do new search.
/**********************************************************************************************************************************/
if you are using <rich:dataGrid> and your scroller is <t:dataScroller> then
<rich:dataGrid
id="data"
var="item"
columns="3"
elements="6"
width="600px"
value="#{IFussBean.searchVideoList}"
binding="#{IFussBean.iFussDataGrid}"
>
Declare HtmlDataGrid in Bean:
private HtmlDataGrid iFussDataGrid;
Its getter and setter
public HtmlDataGrid getiFussDataGrid() {
return iFussDataGrid;
}
public void setiFussDataGrid(HtmlDataGrid iFussDataGrid) {
this.iFussDataGrid = iFussDataGrid;
}
Now define its action listener in Bean which will invoke on pressing command button for search :
public void resetDataScroller(ActionEvent e) {
if(iFussDataGrid != null) {
iFussDataGrid.setFirst(0);
}
}
Invoke ActionListener on command button
<h:commandButton styleClass="submit-button" actionListener="#{IFussBean.resetDataScroller}" action="#{IFussBean.searchLocation}" image="images/submit-button.png"/>
It also give desire result.
I am creating registration form in JSF and I have field as Active, Inactive where I need to use check boxes and these checkboxes should be SINGLE SELECT ONLY. (Note: I can use radio button and solve the problem, however due to some problem I have to use check boxes).
Please suggest me how to get this done?
Thanks in advance...
I think what you need is <h:selectBooleanCheckbox>. The value binded to this component can only be either true (Active) or false (Inactive). It will be something like the following:
<h:selectBooleanCheckbox id="active" value="#{mrBean.active}" >
<f:ajax render="inactive" listener="#{mrBean.onActiveStatusChange}" />
</h:selectBooleanCheckbox>
<h:selectBooleanCheckbox id="inactive" value="#{mrBean.inactive}" >
<f:ajax render="active" listener="#{mrBean.onInactiveStatusChange}" />
</h:selectBooleanCheckbox>
#ManagedBean
#RequestScoped
public class MrBean {
private boolean active;
private boolean inactive;
#PostConstruct
public void prepareMrBean() {
this.active = true;
}
public void onActiveStatusChange() {
if (active) inactive = false;
}
public void onInactiveStatusChange() {
if (inactive) active = false;
}
}
I have a problem with selecting rows in the Primefaces Datatable. I use dynamic columns, so the standard row selection mechanism is not usable here, I implement checkbox selection myself.
To help, here's s simplified version of what I have in my xhtml:
<h:form>
<p:dataTable id="table"
var="result"
value="#{tableBean.results}">
<p:columns value="#{tableBean.columnNames}" var="column" columnIndexVar="colIndex">
<f:facet name="header">
#{column}
</f:facet>
<h:panelGroup rendered="#{colIndex==0}">
<h:outputLabel>#{rowIndex}</h:outputLabel>
<h:selectBooleanCheckbox value="#{tableBean.selectedRows[result[0]]}"/>
</h:panelGroup>
</p:columns>
</p:dataTable>
<h:commandButton value="Submit"></h:commandButton>
</h:form>
And here's what I have in the managed bean to select the checkboxes:
package testpackage;
import java.util.*;
import javax.faces.bean.*;
#ManagedBean
#SessionScoped
public class TableBean
{
private Map<String, Boolean> selectedRows = new HashMap<String, Boolean>();
List<List<String>> results = new LinkedList<List<String>>();
public TableBean()
{
List<String> row1 = new LinkedList<String>();
List<String> row2 = new LinkedList<String>();
row1.add("row1.ref");
row1.add("row1.id");
row1.add("row1.status");
row2.add("row2.ref");
row2.add("row2.id");
row2.add("row2.status");
results.add(row1);
results.add(row2);
//selectedRows.put("row2.ref", true);
}
public Map<String, Boolean> getSelectedRows()
{
return selectedRows;
}
public String submit()
{
List<List<String>> selectedResults = new ArrayList<List<String>>();
for (List<String> result : results)
{
if (selectedRows.get(result.get(0)) != null)
{
selectedResults.add(result);
selectedRows.remove(result.get(0));
}
}
return null;
}
public List<List<String>> getResults()
{
return results;
}
public List<String> getColumnNames()
{
List<String> columnNames = new LinkedList<String>();
columnNames.add("");
columnNames.add("REF");
columnNames.add("ID");
columnNames.add("STATUS");
return columnNames;
}
}
The getSelectedRows method works great, but the problem is that the setSelectedRows method is never called, so I don't know which checkboxes the user has selected. Maybe I overlook something very trivial, but cannot find the solution.
Any ideas on this? I would be very glad if you helped, or give any other row selection solution for the dynamic columns.
Thx in advance,
Levi
To me it looks you are rendering the wrong field in selectBooleanCheckBox.
You should be using variable or field from the result variable.
My solution:
In your situation you are rendering an object from List as a form of table row so if you want to make some changes and retrieve the status of that row then you should be using the variable from that object only.
I understand you are submitting the whole form and want to pickup all updated rows, in that case you will have to loop through the whole List and find all the rows which have been updated by checking the status in Request Handler(Action) bean.
Hope that helps.
The setter is never called for nested objects. You're the one who's responsible for creating them, not JSF. JSF just gets the nested object and then calls the setter on it (which is the put() method in case of a Map). You just need to determine the selected rows in the action method. Add an action method to the commandbutton:
<h:commandButton value="Submit" action="#{bean.submit}"></h:commandButton>
which is definied like follows (guessing/assuming that var="result" is in essence an Object[]):
public String submit() {
List<Object[]> selectedResults = new ArrayList<Object[]>();
for (Object[] result : results) {
if (selectedRows.get((String) result[0])) {
selectedResults.add(result);
selectedRows.remove(result[0]); // Reset.
}
}
// Now selectedResults contains all selected results.
}