Primefaces Dropdown with Datatable - jsf

Im trying to implement a JSF-Webapp with Primefaces. In that case i need a Dropdown with a Datatable inside.
The datatable contains over 30.000 entries (3 columns). I already implemented a datatable with virtual scrolling that works fine (i still need to think about initial data loading, maybe its possible to load data only from db, if end of view is reached).
Idea is a dropdown with a String as value (generated from database) and after clicking on the dropdown, you see the datatable, where the user can choose and select one. The selected should be written into database after submit.
<p:selectOneMenu>
<f:selectItems>
<p:dataTable var="entry" value="#{scrollView.lazyModel}"
scrollRows="20" scrollable="true" virtualScroll="true"
scrollHeight="200" lazy="true" rows="40" style="margin-bottom:0">
<p:column headerText="e1" footerText="e1">
<h:outputText value="#{entry.e1}" />
</p:column>
<p:column headerText="e2" footerText="e2">
<h:outputText value="#{entry.e2}" />
</p:column>
<p:column headerText="e3" footerText="e3">
<h:outputText value="#{entry.e3}" />
</p:column>
</p:dataTable>
</f:selectItems>
</p:selectOneMenu>
EDIT: I found a solution to get columns in my dropdown (thx!), but if i solve it this way, i cant use virtual scrolling. My problem is, that i dont know how to check, if scrollbar is at bottom of the dropdown. My idea was to check and if true reload the selectonemenu with new data.
XHTML:
<p:selectOneMenu id="test"
value="#{bean.dto == null ? '': bean.dto}"
var="d">
<f:selectItem
itemLabel="#{bean.dto == null ? '': bean.dto}" />
<f:selectItems value="#{docScroll.currentData}" var="doc" itemValue="#{doc}"
itemLabel="#{doc.forename} #{doc.surname}, #{doc.city}" />
<p:column>
#{d.surname}
</p:column>
<p:column>
#{d.forename}
</p:column>
<p:column>
#{d.city}
</p:column>
<f:ajax event="change" onevent="#{scripts.checkScrollBottom}" listener="#{docScroll.reloadData}" update="test"/>
</p:selectOneMenu>
reloadData:
public void reloadData() {
if (pos == data.size() - 1) {
return;
}
pos += range - 1;
if (pos >= data.size()) {
pos = data.size() - 1;
}
currentData = data.subList(0, pos);
}
checkScrollBottom:
function checkScrollBottom(event){
var source = event.target;
if(source.offsetHeight + source.scrollTop == source.scrollHeight){
alter("END!!");
}
}

Related

Cannot style <p:column> inside <p:selectOneMenu> when using <f:selectItem value=List<SelectItem> />

I am using List< SelectItem > to Group passed and failed sessions:
runSessionId = selectedTestSession.getRunSessionId();
failedLoopsSelectGroup = new SelectItemGroup("Failed");
failedLoopsSelectGroup.setSelectItems(new SelectItem[]{});
passedLoopsSelectGroup = new SelectItemGroup("Passed");
passedLoopsSelectGroup.setSelectItems(new SelectItem[]{});
loopsGroup = new ArrayList<>();
loopsGroup.add(failedLoopsSelectGroup);
loopsGroup.add(passedLoopsSelectGroup);
I am using this List inside <p:selectOneMenu> and it displays just fine, but the problem is that I cannot style the drop down items based on if it is passed or failed.
<p:selectOneMenu id="loopDropDown"
value="#{diagsBean.displayLoop}"
style="margin-right: 10px;">
<f:selectItems value="#{diagsBean.loopsGroup}" var="loopObj"/>
<p:column>
<h:outputText value=#{loopObj.description} class="#
{loopObj.description eq 'Passed' ? 'good' : 'warning'}"
</p:column>
<p:ajax event="itemSelect"
listener="#{diagsBean.onLoopSelect}"
onstart="PF('processing').show();"
oncomplete="PF('processing').hide();"
process="#this"
update="#(.failFilter)"/>
</p:selectOneMenu>
Even if I style the column itself and give it a background color it does not appear.

How to filter a p:dataTable with selectionMode with p:selectCheckboxMenu?

I'm trying to filter a p:dataTable with Primefaces component p:selectCheckboxMenu in one column header. This however, does not work as intended. The other filters on the datatable work just fine, such as input fields.
The column in question is the Room type, that has the p:selectCheckboxMenu.
The filtering works once, after that checking or unchecking boxes on the selectCheckbox menu doesn't add or remove any filtering on the table.
Here's an interesting bit on the problem:
If I remove the selectionMode="single" attribute from the datatable, then the sorting works even after the first checkBox toggle. As in, I can toggle and untoggle a box and the p:dataTable gets filtered accordingly. But, I need the selection mode here, since I'm supposed to be able to select a row and navigate to another view by clicking it. That doesn't work when there's no selectionMode attribute on the datatable.
Here's my datatable:
<div class="background">
<div class="freeRoomsContent">
<br/>
<p:outputLabel value="free rooms" styleClass="headerfont"/>
<br/>
<h:form id="freeRoomsForm">
<p:dataTable id="freeRoomsTable" var="room" paginatorPosition="bottom" paginatorAlwaysVisible="false"
value="#{freeRoomsController.freeRoomsList}" selectionMode="single" selection="#{freeRoomsController.room}"
rowKey="#{room.roomId}" widgetVar="freeRoomsTable"
paginator="true" rows="20" pageLinks="5" scrollable="false"
paginatorTemplate="{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="20,50,100" skipChildren="true" emptyMessage="No free rooms available.">
<p:ajax event="rowSelect" listener="#{freeRoomsController.onRowSelect}" />
<p:column headerText="Room Id" sortBy="#{room.roomId}" filterMatchMode="contains" filterBy="#{room.roomId}">
<h:outputText value="#{room.roomId}"/>
</p:column>
<p:column headerText="Room number" sortBy="#{room.roomNumber}" filterMatchMode="contains" filterBy="#{room.roomNumber}">
<h:outputText value="#{room.roomNumber}" />
</p:column>
<!-- other similar columns -->
<p:column headerText="Room type" filterMatchMode="exact" filterBy="#{room.roomType}">
<f:facet name="filter">
<p:selectCheckboxMenu onchange="PF('freeRoomsTable').filter()"
label="Room type">
<f:selectItems value="#{staticData.roomTypes}" var="rt" itemLabel="#{msg[rt.name]}" itemValue="#{rt.name}"
/>
<p:ajax event="change" process="#this" update="freeRoomsForm" />
<p:ajax event="toggleSelect" process="#this" update="freeRoomsForm" />
</p:selectCheckboxMenu>
</f:facet>
<h:outputText value="#{msg[room.roomtype.name]}">
<f:convertDateTime pattern="dd.MM.yyyy" />
</h:outputText>
</p:column>
<!-- normal input field columns that work -->
</p:dataTable>
</h:form>
</div>
</div>
This worked for me:
Using value and filteredValue in p:dataTable
Use only onchange=PF('freeRoomsTable').filter(), without child p:ajax elements in p:selectCheckboxMenu
Set value attribute for p:selectCheckboxMenu, e.g. value="#{someBean.selectedItems}"
In your bean, use private String[] selectedItems, with getter and setter
In your bean implement filterFunction, method need to have signature boolean (Object, Object, Locale) altough for this example only 1st argument (Object value) is used:
public boolean filterFunction(Object value, Object filter, Locale locale) {
// instanceof checking probably not needed
if (value == null || !(value instanceof String)) {
return true;
}
String valueInRow = (String)value;
// if nothing is selected, show row in table i.e. return true,
// you can play with this ofcourse
if (selectedItems == null || selectedItems.length == 0) {
return true;
}
// if item in row matches any of the items that were selected in header,
// show in table i.e. return true
for (int i = 0; i < selectedItems.length; i++) {
if (selectedItems[i].equals(valueInRow)) {
return true;
}
}
// if you don't want to show row in table, return false
return false;
}
In p:column, call filterfunction=#{someBean.filterFunction} - no arguments, no parenthesis, no need to use any filterMatchMode, leave only filterBy

h:selectOneMenu value should change onclick of p:selectBooleanCheckbox

I have a problem in my application.
I have a datatable, inside that one selectBooleancheckbox , selectonemenu with items("Confirmed", "Rejected" ,"selected") and one inputText is there. I need to write code for,
if selectbooleancheckbox is checked then the selectonemenu will get the value "Selected" and the inputText also become editable.
this is my xhtml code:
<p:dataTable id="panel1"
rendered="true"
var="step2table"
value="#{dtstep2_tab1.step2table}"
editMode="cell"
scrollable="true"
selection="#{dtstep2_tab1.selectedrows}"
rowKey="#{step2table.rs2_empname}"
rowSelectMode="checkbox"
rowStatePreserved="true">
<p:column headerText="Select" id="hSelect" style="font-size:12px;width:60px;">
<p:selectBooleanCheckbox id="Booleanchkbox" >
<p:ajax listener="#{dtstep2_tab1.UpdateStatus}" update="panel1" />
</p:selectBooleanCheckbox>
</p:column>
<p:column headerText="Status" id="hStatus" style="font-size:12px;width:100px;">
<h:selectOneMenu id="cbo" value="#{step2table.rs2_status}" >
<f:selectItem itemLabel="Confirmed" itemValue="Confirmed"></f:selectItem>
<f:selectItem itemLabel="Selected" itemValue="Selected"></f:selectItem>
<f:selectItem itemLabel="Rejected" itemValue="Rejected"></f:selectItem>
</h:selectOneMenu>
</p:column>
<p:column style="font-size:12px;width:150px;">
<f:facet name="header">
<h:outputText value="Comments"></h:outputText>
</f:facet>
<h:inputText value="#{step2table.rs2_comments}" rendered="#{dtstep2_tab1.editable}"/>
</p:column>
</p:dataTable>
and in bean I have the following code in addition with getter and setter method.
public void UpdateStatus(AjaxBehaviorEvent event) {
SelectBooleanCheckbox permit = (SelectBooleanCheckbox) event.getComponent();
boolean checked = (Boolean) permit.getValue();
if (checked) {
setRs2_status("Selected");
setEditable(true);
setSelect(true);
}
else
{
setEditable(false);
setSelect(false);
}
}
I don't know what I am doing wrong here. Please guide me on the issue.

delete from datatable without affecting checkbox event

I have a datatable in which first component is delete button and last is checkbox.
Now problem is that when I delete a row it reset the checkbox selected in other row
I dont want to uncheck the selected checkbox in other row.
<h:dataTable id="languageTableBody" value="#{countryBean.countryLanguageList}" var="countryLangObj" >
<h:column>
<f:facet name="header">#{msg['country.language.label.delete']}</f:facet>
<p:commandLink action="#{countryBean.deleteRow}" immediate="true" update="#form" process="#this">
<h:graphicImage value="../images/delete.png" />
<f:setPropertyActionListener target="#{countryBean.langId}" value="#{countryLangObj.language.languageCode}" />
</p:commandLink>
</h:column>
<h:column>
<f:facet name="header">#{msg['country.language.label.assignlanguage']}</f:facet>
<h:inputText readonly="true" value="#{countryLangObj.language.languageName}" id="languageName" />
</h:column>
<h:column>
<f:facet name="header">#{msg['country.language.label.languagecode']}</f:facet>
<h:inputText readonly="true" value="#{countryLangObj.language.languageCode}" />
</h:column>
<h:column>
<f:facet name="header">#{msg['country.language.label.defaultlanguage']}</f:facet>
<h:selectBooleanCheckbox id="checkBox" value="#{countryLangObj.isDefaultLanguage}" onclick="dataTableSelectOneRadio(this)" />
</h:column>
</h:dataTable>
countryBean.java
public String deleteRow(){
System.out.println("deleteRow()::Enter");
String delLangId = getLangId();
System.out.println("getLangId(): "+getLangId());
if(null != delLangId && delLangId.trim().length() > 0){
System.out.println("Delete Language Code: "+delLangId);
List<CountryLanguageDTO> countryLangList = getCountryLanguageList();
System.out.println("countryLangList: "+ (null == countryLangList));
List<CountryLanguageDTO> tempCountryLangList = new ArrayList<CountryLanguageDTO>();
for (CountryLanguageDTO countryLanguage : countryLangList) {
System.out.println("wewewewew: "+delLangId.equalsIgnoreCase(countryLanguage.getLanguage().getLanguageCode()));
if(!delLangId.equalsIgnoreCase(countryLanguage.getLanguage().getLanguageCode())){
tempCountryLangList.add(countryLanguage);
}
}
setCountryLanguageList(tempCountryLangList);
}
return SUCCESS;
}
addCountry.js
function dataTableSelectOneRadio(radio) {
var id = radio.name.substring(radio.name.lastIndexOf(':'));
var el = radio.form.elements;
for (var i = 0; i < el.length; i++) {
if (el[i].name.substring(el[i].name.lastIndexOf(':')) == id) {
el[i].checked = false;
}
}
radio.checked = true;
}
It happens because of this:
<p:commandLink action="#{countryBean.deleteRow}" immediate="true" update="#form" process="#this">
When clicking the button, you will transmit the form with the checkboxes. But because of process="#this" you will not convert/validate/store any inputs. The only thing that will get processed is the button itself. After that, because of update="#form" the whole form (including the table with the checkboxes) will be re-rendered. But with the old values.
Thus the solution is to either change process="#this" to #form or to add Ajax functionality to store the new values of each checkbox every time the value changes.
It could be a problem with bean scope. If scenario is like:
Precondition:
-Table are just showed.
Scenario:
-Select some checkbox.
-Delete row
Current result
-Selected checkbox is unchecked.
So after delete row you propably reinit view so all data get default state.
Try to change your scope to View(CDI) or Session.

RadioButton row select event in p:datatable

RadioButton/Checkbox based row selection is a common use case and DataTable provides a solution for this with column selection mode feature.
<p:dataTable var="car" value="#{tableBean.cars}" paginator="true" rows="10"
selection="#{tableBean.selectedCar}">`
<f:facet name="header">
RadioButton Based Selection
</f:facet>
<p:column selectionMode="single" />
<p:column headerText="Model">
<h:outputText value="#{car.model}" />
</p:column>
<p:column headerText="Year">
<h:outputText value="#{car.year}" />
</p:column>
<p:column headerText="Manufacturer">
<h:outputText value="#{car.manufacturer}" />
</p:column>
<f:facet name="footer">
<p:commandButton value="View" image="ui-icon ui-icon-search"
update="displaySingle" oncomplete="singleCarDialog.show()"/>
</f:facet>
</p:dataTable>
I want to know if I choose the first column's radioButton ,how I get a event for this.
Because I want to let a button disabled when choose the first column or the last column's radioButton .
And I also want to get the index of the column when selected the column ,Now I use the selectedCar to compare the list,and get the index of the column. It looks ugly.Anyone can help me ?
This is a solution for PrimeFaces <= 2.x only.
There is a good example at Primeface's showcase. There is an attribute rowSelectListener that can be used like this:
rowSelectListener="#{tableBean.onRowSelect}"
and in the backing bean:
public void onRowSelect(SelectEvent event) {
FacesMessage msg = new FacesMessage("Car Selected",
((Car) event.getObject()).getModel());
FacesContext.getCurrentInstance().addMessage(null, msg);
}

Resources