I have a dataTable in primefaces and wish to select multiple rows, but the checkbox doesn't highlight when I hover over it and can't be selected when I click.
The checkbox is definitely enabled. Here is the code:
<p:dataTable id="deferDatatable2"
value="#{deferMaintenanceTasksBean.tasksList}"
var="tasks"
rowKey="tasks.jobId"
selection="#{deferMaintenanceTasksBean.maintenanceTaskDatas}"
styleClass="editable-datatable" >
<p:ajax event="toggleSelect"
listener="#{deferMaintenanceTasksBean.toggleSelect()}" />
<p:ajax event="rowSelectCheckbox"
update="deferDatatable2" />
<p:ajax event="rowUnselectCheckbox"
update="deferDatatable2" />
<p:ajax event="rowSelect"
update="deferDatatable2" />
<p:ajax event="rowUnselect"
update="deferDatatable2" />
<p:column styleClass="select-column"
rendered="#{tasks.task.deferrable == 'true'}"
selectionMode="multiple" >
</p:column>
<p:column headerText="Task Code"
rendered="#{tasks.task.deferrable == 'true'}">
<h:outputText value="#{tasks.task.taskCode}" />
</p:column>
<p:column headerText="Job Code"
rendered="#{tasks.task.deferrable == 'true'}">
<h:outputText value="#{tasks.jobCode.code}" />
</p:column>
<p:column headerText="Description"
rendered="#{tasks.task.deferrable == 'true'}">
<h:outputText value="#{tasks.task.description}" />
</p:column>
<p:column headerText="Safety Critical"
rendered="#{tasks.task.deferrable == 'true'}">
<p:selectBooleanCheckbox value="#{tasks.task.safetyCritical}"
disabled="true" />
</p:column>
<p:column headerText="Deferrable?"
rendered="#{tasks.task.deferrable == 'true'}">
<p:selectBooleanCheckbox value="#{tasks.task.deferrable}"
disabled="true" />
</p:column>
<p:column headerText="Att."
rendered="#{tasks.task.deferrable == 'true'}">
<h:outputText id="i4AttachmentOutLbl"
value="#{tasks.task.attachmentCount}" />
</p:column>
</p:dataTable>
Inside the toggleSelect method there is just a log so I could see if the method is being called even though the checkboxes aren't being checked, but it isn't.
Like I say, the checkboxes all render as does everything else, and they aren't faded as if they were disabled, but they behave as if they were disabled. I have tried removing the styleClasses to see if they were somehow affecting things, but they aren't.
I have other working examples of this within my project and from what I can see I have set this dataTable up exactly the same, but for some reason it isn't working. The xhtml has the same ui:compposition and same outputStylesheets and outputScripts as these other pages and same basic layout, so I am convinced there is something I have missed from the dataTable, but no clue what.
I have added a little test table as follows with a list of strings called testList and this has worked. Not sure why this could be...
<p:dataTable id="testTable"
value="#{deferMaintenanceTasksBean.testList}"
var="test"
rowKey="test"
selection="#{deferMaintenanceTasksBean.testListSelect}">
<p:ajax event="toggleSelect"
listener="#{deferMaintenanceTasksBean.toggleSelect(1)}" />
<p:ajax event="rowSelectCheckbox"
update="testTable" />
<p:ajax event="rowUnselectCheckbox"
update="testTable" />
<p:ajax event="rowSelect"
update="testTable" />
<p:ajax event="rowUnselect"
update="testTable" />
<p:column selectionMode="multiple" />
<p:column>
<h:outputText value="#{test}" />
</p:column>
</p:dataTable>
Any suggestions appreciated.
Thanks
The removal of the rendered tags in your columns should then allow you to select the check boxes. I presume this is because it removes the top of your table and the toggle all check box causing the rest to fail silently
Related
I can not correctly view the contents of a column with selectManyCheckbox in p:dataTable.
Here my .xhtml:
<h:form id="projAccess" enctype="multipart/form-data">
<p:dataTable tableStyle="width:auto" id="i_dtb2" var="p" value="#{comBean.l_uSrcRes}" paginator="true" rows="5" rowsPerPageTemplate="5,10"
paginatorPosition="bottom">
<p:columnGroup type="header">
<p:row>
<p:column rowspan="2" headerText="User" />
<p:column rowspan="2" headerText="Asset" />
<p:column colspan="6" headerText="Roles" />
<p:column rowspan="2" colspan="2" headerText="Action" />
</p:row>
<p:row>
<p:column headerText="Project Manager"></p:column>
<p:column headerText="Project Manager Deputy"></p:column>
<p:column headerText="Business Analyst"></p:column>
<p:column headerText="Functional Analyst"></p:column>
<p:column headerText="Technical Analyst"></p:column>
<p:column headerText="Developer"></p:column>
</p:row>
</p:columnGroup>
<p:column>
<h:outputText value="#{p.usercd}" />
</p:column>
<p:column>
<h:outputText value="#{p.asset}" />
</p:column>
<p:column colspan="6">
<h:panelGroup layout="block" >
<p:selectManyCheckbox columns="6" value="#{p.rolesList}">
<f:selectItems value="#{comBean.l_roles}" var="role" itemLabel="#{role}" itemValue="#{role}" />
</p:selectManyCheckbox>
</h:panelGroup>
</p:column>
<p:column>
<p:commandButton action="#{comBean.m_updateAccess}" ajax="false" icon="ui-icon-pencil">
<f:setPropertyActionListener value="#{p}" target="#{comBean.f_selectedUser}" />
<f:param name="area" value="project" />
</p:commandButton>
</p:column>
<p:column>
<p:commandButton action="#{ubean.m_deleteUser}" ajax="false" icon="ui-icon-trash">
<f:setPropertyActionListener value="#{p}" target="#{comBean.f_selectedUser}" />
<f:param name="area" value="project" />
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
Here the result:
How can I adapt content to header columns?
You are using tableStyle="width:auto" in your p:dataTable.
Removing this will align the checkboxes to its respective columns but you can notice that the columns are still a little bit misaligned.
To solve this, you can add style="padding:0px;" on your checkbox p:column.
Your code will look something like this.
<p:dataTable id="i_dtb2" var="p" value="#{comBean.l_uSrcRes}" paginator="true" rows="5" rowsPerPageTemplate="5,10"
paginatorPosition="bottom">
// other codes
<p:column colspan="6" style="padding:0px;">
// other codes
</p:column>
// other codes
</p:dataTable>
On another note, if your functional specification allows it, you can remove [Project Manager, Project Manager Deputy, etc] headers, since your are displaying them right next to the checkboxes.
You will have to remove p:columnGroup and set the headerText to their respective columns with "Roles" as headerText for your checkBox column.
Hope this helps.
I want to create webpage having table with radio buttons in primefaces using datatable component like below.
I found one solution to implement custom component as mentioned in http://www.javaworld.com/article/2077687/enterprise-java/group-radio-buttons-inside-a-jsf-datatable-component.html for JSF.
But it is time taking and a lot of code.
Primefaces provides the custom layout for selectOneRadio. I implemented the table using the custom layout example of selectOneRadio as below. In this first column has width zero which contains the radio button.
<p:dataTable id ="employeeTable" rowIndexVar="rowId" var ="emp" value ="#{employeeList.employeeData}" widgetvar ="employeeTable" resizableColumns="true">
<p:column headerText="" style="width:0px;">
<p:selectOneRadio id="action" value="#{emp.status}" layout ="custom">
<f:selectItem itemLabel="Yes" itemValue="Yes" />
<f:selectItem itemLabel="No" itemValue="No" />
<f:selectItem itemLabel="Amendment" itemValue="Amendment" />
<f:selectItem itemLabel="KIV" itemValue="KIV" />
</p:selectOneRadio>
</p:column>
<p:column headerText="Personnel No">
<h:outputText value="#{emp.perNum}" />
</p:column>
<p:column headerText="Empl Name">
<h:outputText value="#{emp.name}" />
</p:column>
<p:column headerText="Yes">
<p:radioButton for="action" itemIndex="0" />
</p:column>
<p:column headerText="No">
<p:radioButton for="action" itemIndex="1" />
</p:column>
<p:column headerText="Amendment">
<p:radioButton for="action" itemIndex="2" />
</p:column>
<p:column headerText="KIV">
<p:radioButton for="action" itemIndex="3" />
</p:column>
</datatable>
Use p:selectOneRadio outside of your dataTable with layout attribute set to "custom". Fill this radio with f:selectItems same as data provided to dataTable via "value" parameter.
<p:selectOneRadio id="customRadio"
value="#{beanMB.selectedItem}"
layout="custom">
<f:selectItems value="#{beanMB.tableItems}"
var="item"
itemValue="#{item.radioValue}"
itemLabel="#{item.radioLabel}"/>
</p:selectOneRadio>
In dataTable column use p:radioButton with itemIndex matching current rowIndex.
<p:dataTable var="item"
rowIndexVar="rowIndex"
value="#{beanMB.tableItems}">
<p:column headerText="Choice">
<p:radioButton for="#form:customRadio"
itemIndex="#{rowIndex}"
rendered="#{item.radioRendered}"/>
</p:column>
</p:dataTable>
I have a dataTable with cell editor. And I want to only have some (selected) rows editable. And when the user uses the cell editor, I want to perform input validation immediately after the value is set.
So I use cellEdit event in the data table and from the event handler I trigger validation failure.
<p:ajax event="cellEdit" listener="#{bean.onEditCell}" update=":formId:propertySelect" />
This works like a charm. If the user enters an invalid value, the editor doesn't close and the error message is displayed.
What doesn't work is the user inputting a valid value afterwards. The cellEdit event does not trigger again since the form is in "input validation failure state".
I have lost a day trying to resolve that:
I want to reset input validation when a user sets a new value - resetInput only works from buttons. I couldn't get it working on value change.
I didn't find how to reset the field from JavaScript directly.
if I combine "onchange" event and "remoteCommand" a handler is called in the backing bean, but then I cannot find the UIInput to call resetValue() on it.
<p:dataTable id="propertySelect" value="#{bean.propertyValues}" var="prop"
editable="true" editMode="cell" scrollable="true"
scrollHeight="200" widgetVar="propSelectTable"
filteredValue="#{bean.filteredPVs}">
<p:ajax event="cellEdit" listener="#{bean.onEditCell}" update=":#{formId}:propertySelect" />
<p:ajax event="filter" oncomplete="updateToggle()" />
<p:column id="rowSelection">
<f:facet name="header">
<p:selectBooleanCheckbox id="toggleAll" value="#{bean.selectAllRows}">
<p:ajax listener="#{bean.handleToggleAll}" update=":#{formId}:propertySelect" />
</p:selectBooleanCheckbox>
</f:facet>
<p:selectBooleanCheckbox value="#{prop.selected}">
<p:ajax update=":#{formId}:propertySelect" oncomplete="updateToggle()" listener="#{bean.rowSelectListener(prop)}"/>
</p:selectBooleanCheckbox>
</p:column>
<p:column headerText="Property">
<h:outputText value="#{prop.name}" />
</p:column>
<p:column headerText="Description">
<h:outputText value="#{prop.description}" />
</p:column>
<p:column headerText="Value">
<p:cellEditor rendered="#{prop.selected}">
<f:facet name="output">
<h:outputText value="#{bean.displayPV(prop)}" />
</f:facet>
<f:facet name="input">
<p:inputText id="pvSimple" value="#{prop.uiValue}" rendered="#{prop.propertyValueUIElement eq 'INPUT'}" />
<p:inputTextarea id="pvArea" rows="7" value="#{prop.uiValue}"
rendered="#{prop.propertyValueUIElement eq 'TEXT_AREA'}" />
<p:selectOneMenu id="pvEnum" value="#{prop.uiValue}"
rendered="#{prop.propertyValueUIElement eq 'SELECT_ONE_MENU'}">
<f:selectItem itemLabel="<Select value>" itemValue="" />
<f:selectItems value="#{prop.enumOptions}" var="enum" itemLabel="#{enum}" itemValue="#{enum}" />
</p:selectOneMenu>
</f:facet>
</p:cellEditor>
<h:outputText value="-" rendered="#{!prop.selected}" />
</p:column>
I am looking for a way to clear input validation errors on the input fields with the ids "pvSimple", "pvArea" or "pvEnum".
What is the filter match mode for global filter (not the individual column filter which defaults to 'startsWith') and how to change it?
The reason I ask is, when I use the global filter with match mode set to 'startsWith' in all my columns, still I get values with 'contains' filter mode. See screenshot below.
I shouldn't be getting the rows other than the first row as I specified 'startsWith' in all columns.
Here is my datatable,
<h:form id="countryTable">
<p:dataTable rowKey="" value="#{countryBean.countriesList}"
var="country" selection="#{countryBean.selectedCountries}"
styleClass="data-table-style" widgetVar="countryTableWVar"
filteredValue="#{countryBean.filteredCountries}">
<f:facet name="header">
<div class="align-left">
<p:outputPanel>
<h:outputText value="Search all fields:" />
<p:inputText id="globalFilter" onkeyup="countryTableWVar.filter();"
style="width:150px" />
</p:outputPanel>
</div>
</f:facet>
<p:column selectionMode="multiple" style="width:2%;" />
<p:column headerText="Numeric Code" filterMatchMode="startsWith"
filterStyle="display:none" filterBy="numericCode">
<h:outputText value="#{country.numericCode}"></h:outputText>
</p:column>
<p:column headerText="Alpha_2 Code" filterMatchMode="startsWith"
filterStyle="display:none" filterBy="alpha2">
<h:outputText value="#{country.alpha2}"></h:outputText>
</p:column>
<p:column headerText="Alpha_3 Code" filterMatchMode="startsWith"
filterStyle="display:none" filterBy="alpha3">
<h:outputText value="#{country.alpha3}"></h:outputText>
</p:column>
<p:column headerText="Name" filterMatchMode="startsWith"
filterStyle="display:none" filterBy="name">
<h:outputText value="#{country.name}"></h:outputText>
</p:column>
</p:dataTable>
</h:form>
How to change the datatable global filter match mode?
If you look at the source code of primefaces
org.primefaces.component.datatable.feature.FilterFeature.java
At line 133 you can see primefaces uses contains method of String
if(columnValue.toLowerCase(filterLocale).contains(globalFilter)){
globalMatch = true;
}
So for now there is no way other than changing code according to your needs and building your own primefaces jar.
From Primefaces 4.0 docs:
Filter located at header is a global one applying on all fields, this is implemented by calling client
side API method called filter(), important part is to specify the id of the input text as globalFilter
which is a reserved identifier for datatable.
The use case would be:
<p:dataTable var="car" value="#{carBean.cars}"
filteredValue="#{carBean.filteredCars}" widgetVar="carsTable">
<f:facet name="header">
<p:outputPanel>
<h:outputText value="Search all fields:" />
<h:inputText id="globalFilter" onkeyup="PF('carsTable').filter()" />
</p:outputPanel>
</f:facet>
<p:column filterBy="model" headerText="Model" filterMatchMode="contains">
<h:outputText value="#{car.model}" />
</p:column>
<p:column filterBy="year" headerText="Year" footerText="startsWith">
<h:outputText value="#{car.year}" />
</p:column>
<p:column filterBy="manufacturer" headerText="Manufacturer"
filterOptions="#{carBean.manufacturerOptions}" filterMatchMode="exact">
<h:outputText value="#{car.manufacturer}" />
</p:column>
<p:column filterBy="color" headerText="Color" filterMatchMode="endsWith">
<h:outputText value="#{car.color}" />
</p:column>
</p:dataTable>
It doesn't tell anything about startsWithor endsWith specific cases for global filter. It could be interesting to open a thread on the issue tracker.
I've been running Primefaces 3.0, no issues, and now am trying an upgrade to 3.4.x - I've tried 3.4, 3.4.1, and 3.4.2 and this problem occurs in all 3 - basically for the datatable with the selectionMode="single" option when I click on a row it remains selected no matter how many other rows I select. At the same time I'm quite sure the selection="#{databrowser.selectedData}" variable is not being set when I'm clicking on the rows. The table is fully populated and no 2 rows have the exact same data in all columns. Tested and this occurs in both Chrome and Firefox. I can't find any similar problem posted - wondering if anyone else has had this issue?
Apart from the element referencing this is the 3.0 code I've used:
<p:layoutUnit position="center" resizable="true" header="Data Set Details" styleClass="east_panel_header" >
<h:form id="tblbrowser">
<p:dataTable id="dataTable" emptyMessage="No data sets found." style="width: 100%" var="datlis" resizableColumns="true" value="#{databrowser.selectedDataModel}" widgetVar="dataTable" selection="#{databrowser.selectedData}" selectionMode="single" >
<p:ajax event="rowSelect" update=":usercomments:commentsTable, :tblbrowser:dataTable" />
<f:facet name="header" >
<p:outputPanel>
<h:outputText value="Search all fields " />
<p:inputText id="globalFilter" onkeyup="dataTable.filter()"/>
</p:outputPanel>
</f:facet>
<p:column id="owner" filterBy="#{datlis.uname}" headerText="Added By" filterMatchMode="contains" >
<h:outputText value="#{datlis.uname}" />
</p:column>
<p:column id="name" filterBy="#{datlis.name}" headerText="Name" >
<h:outputText value="#{datlis.name}" />
</p:column>
<p:column id="description" filterBy="#{datlis.description}" headerText="Description" filterMatchMode="endsWith" >
<h:outputText value="#{datlis.description}" />
</p:column>
<p:column id="datatype" filterBy="#{datlis.data_type}" headerText="Data Type"
filterOptions="#{databrowser.dataTypeOptions}" filterMatchMode="exact" >
<h:outputText value="#{datlis.data_type}" />
</p:column>
<p:column id="quality" filterBy="#{datlis.quality}" headerText="Source Type"
filterOptions="#{databrowser.qualityOptions}" filterMatchMode="exact" >
<h:outputText value="#{datlis.quality}" />
</p:column>
<p:column id="added" headerText="Date Added" filterMatchMode="endsWith" >
<h:outputText value="#{datlis.added}" />
</p:column>
<p:column headerText="Metadata" style="width:40px" >
<p:commandButton id="selectButton" rendered="#{datlis.has_metadata}" icon="ui-icon-circle-arrow-s" title="View" ajax="false" >
<f:param name="filepath" value="#{datlis.filepath}" />
<p:fileDownload value="#{filedownloader.mfile}" />
</p:commandButton>
</p:column>
<p:column headerText="Data File(s)" style="width:90px" >
<p:commandButton id="selectButton2" rendered="#{datlis.has_datafiles}" icon="ui-icon-circle-arrow-s" title="View" ajax="false" >
<f:param name="datafiles" value="#{datlis.datafiles}" />
<p:fileDownload value="#{filedownloader2.dfile}" />
</p:commandButton>
<h:outputText value=" " />
<h:outputText value="#{datlis.zipsize}" />
</p:column>
</p:dataTable>
</h:form>
</p:layoutUnit>
You are missing the rowKey attribute which should be the unique identifier of each row.
Example, if your selectedData object has a unique field id, your dataTable component should look like:
<p:dataTable id="dataTable" rowKey=#{datlis.id}
value="#{databrowser.selectedDataModel}" var="datlis"
selection="#{databrowser.selectedData}" selectionMode="single" >
No need to update the same table within p:ajax to see the selection, so you can probably remove the :tblbrowser:dataTable from the update target and have only:
<p:ajax event="rowSelect" update=":usercomments:commentsTable" />