Primefaces autocomplete as a datatable filter - jsf

I can't make it work.
Component is sending only part of what is actually in the input. What event should I use to trigger filtering, what option beside forceSelection is needed to actually force selection:
This what is send from a request
InboundShipmentListForm:datalist:j_idt98_input:Select One...
InboundShipmentListForm:datalist:j_idt104_focus:
InboundShipmentListForm:datalist:j_idt104_input:Select One...
InboundShipmentListForm:datalist:j_idt110_input:p
InboundShipmentListForm:datalist:j_idt110_hinput:p
A unexpected error occured! Message: For input string: "p"
<p:column filterBy="#{item.supplierPlant}"
sortBy="#{item.supplierPlant}"
headerText="#{bundle.ListInboundShipmentTitle_supplierPlant}"
style="width:auto; text-align:center">
<!-- autocomplete -->
<f:facet name="header">
<f:facet name="filter">
<p:autoComplete forceSelection="true" itemValue="#{plant}" converterMessage="Select a value"
onchange="PF('datalist').filter()" dropdown="true"
onkeyup="PF('datalist').filter()"
completeMethod="#{inboundShipmentController.completeSuppliers}"
var="plant" itemLabel="#{plant.plantName}"
converter="plantConverter" a:placeholder="Start typing ..." />
</f:facet>
</f:facet>
<h:outputText value="#{item.supplierPlant.plantName}" />
</p:column>

Propably onkeyup event sends string with incomplete value instead the converted plant.
Try to use p:ajax instead onXX events:
<f:facet name="filter">
<p:autoComplete forceSelection="true" itemValue="#{plant}" converterMessage="Select a value"
completeMethod="#{inboundShipmentController.completeSuppliers}"
var="plant" itemLabel="#{plant.plantName}"
converter="plantConverter" a:placeholder="Start typing ...">
<p:ajax event="itemSelect" onstart="PF('datalist').filter()" />
</p:autocomplete>
</f:facet>

Related

How to update a field using a converter and ajax in JSF

I basically have two input field I display if the value is currently empty or null. if it is not, I display an outputText. Those two values are currency values stored in a Long object and I use a converter to display the data properly (I can't use PrimeFaces' inputNumber since I am using PrimeFaces 5.3). My problem is the following :
<c:set var="edtVal1" value="#{bean.val1 ne null and bean.val1 ne 0}" scope="request" />
<c:set var="edtVal2" value="#{bean.val2 ne null and bean.val2 ne 0}" scope="request" />
<p:panelGrid>
<p:row>
<p:column colspan="2">
<p:messages id="mainMessages" globalOnly="false" autoUpdate="true" showDetail="true" />
</p:column>
</p:row>
<!-- [...] -->
<p:row>
<p:column styleClass="col-quarter col-label2">
<h:outputText value="value 1" />
</p:column>
<p:column styleClass="col-quarter col-value2" rendered="#{edtVal1}">
<h:outputText id="val1Output" value="#{bean.val1}" converter="myConverter" />
</p:column>
<p:column styleClass="col-quarter" rendered="#{not edtVal1}">
<p:inputText id="val1Input" value="#{bean.val1}" converter="myConverter">
<p:ajax update="mainMessages val1Input" event="change" />
</p:inputText>
</p:column>
</p:row>
<p:row>
<p:column styleClass="col-quarter col-label2">
<h:outputText value="value 2" />
</p:column>
<p:column styleClass="col-quarter col-value2" rendered="#{edtVal2}">
<h:outputText id="val1Output" value="#{bean.val2}" converter="myConverter" />
</p:column>
<p:column styleClass="col-quarter" rendered="#{not edtVal2}">
<p:inputText id="val1Input" value="#{bean.val2}" converter="myConverter">
<p:ajax update="mainMessages val1Input" event="change" />
</p:inputText>
</p:column>
</p:row>
</p:panelGrid>
when I put it like this, the messages thrown by the converter are displayed, but none of the fields are updated. However, if I use the same boolean variable for both input/output options (changed the variable used in rendered attribute of the 1rst data row to use edtVal2 in both) like so :
<p:row>
<p:column styleClass="col-quarter col-label2">
<h:outputText value="value 1" />
</p:column>
<p:column styleClass="col-quarter col-value2" rendered="#{edtVal1}">
<h:outputText id="val1Output" value="#{bean.val1}" converter="myConverter" />
</p:column>
<p:column styleClass="col-quarter" rendered="#{not edtVal1}">
<p:inputText id="val1Input" value="#{bean.val1}" converter="myConverter">
<p:ajax update="mainMessages val1Input" event="change" />
</p:inputText>
</p:column>
</p:row>
The first field updates successfully and the second once still does not work.
Using a converter to display a formated data is a workaround I already done and it works just as expected and I use the same converter than before. But this time, I don't understand why it's not working.
The converter is important to reproduce the issue, but any custom converter seems to do the job.
Any other solutions are still welcome on this post, but I managed to find a working solution :
when I changed the rendered attribute to a constant string, the issue was absent. So I think the problem comes from a misunderstanding of <c:set>.
My solution was to use a the bean as a controller. I changed the variables from the xhtml file to properties in the controller and now everything works fine. So I removed all <c:set> from my xhtml and use a proper MVC pattern on that page now.
Note :
For those who don't know what MVC is : it's a neat architectural pattern that divides clearly the user interface and manipulated data. Learn more on wikipedia.

Clear input validation error from backing bean

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".

Insert textbox in datatable but having difficulty to save all the records

Hi i am adding a textbox in a datatable where the user will input data in each row. I need help on how to save the data...because right now it's saving only the last row. Please see code below, can someone help on this? I think there should be some sort of array but i dont know if it is possible to store value in array using el expression. I implemented a nested datatable since i want the data to be side by side. If you have a better idea other than using datatable , I would be glad if you could share it and give proper instruction on how to proceed. ( but it should be side by side)
Thanks in advance
<p:dataTable id="dta" value="#{MyCarComponent.model}" var="cur" rows="15" >
<p:column>
<f:facet name="header">
<h:outputText value="Model:" />
</f:facet>
<h:outputText value="#{current.cptModel}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Type:" />
</f:facet>
<p:dataTable id="dta1" value="#{cur.type}" var="curType" rows="15" >
<p:column>
<h:outputText value="#{curType.cptType}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Origin:" />
</f:facet>
<h:form>
<p:dataTable id="dta3" value="#{curType.origins}" var="curOrigin" rows="15" >
<p:column>
<h:outputText value="#{curOrigin.origin}" />
</p:column>
<p:column>
<h:inputText
value="#{MyCarComponent.origindetails.country}"/>
</p:column>
</p:dataTable>
</h:form>
</p:column>
</p:dataTable>
</p:column>
<f:facet name="footer">
<p:commandButton image="save" ajax="false" value="Save" action=" #. {Mycar.saveMyCar(curOrigin.origin,MyCarComponent.origindetails)}" />
</f:facet>
You're currently binding the input field of all rows to one and same bean property. So when JSF processes the form submit in the same sequence as the component tree, the value of each input field will be set in this one and same property. Of course the property will end up being the one of the last row.
You just need to bind the value of the input field to the currently iterated row, the #{curOrigin}. E.g.
<h:inputText value="#{curOrigin.country}" />
Just create the property of there if it doesn't exist yet.

JSF Primefaces datatable match mode for global filter (not individual column)

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.

Datatable not displaying any data but its fine using a pannel grid

i am currently using a pannel grid to display some data retrived from a database, this is working fine, the layout is not perfect but it displays all of the correct data, however i am wanting to use a datatable for looks more than anything, i have tried to use the outputText from the pannel grid but when i run the page it just says no data found, but on the same page the same code displays the data in the pannel grid
what am i doing wrong ?
this is the code for the working pannel grid
<!-- heading -->
<f:facet name="header">
User Details
</f:facet>
<h:outputText value="#{bundle.ViewUserdetailsLabel_id}"/>
<!-- adding in a small effect here that will fade a message when a user hovers over the id number or username -->
<h:outputLink id="id1" value="#">
<h:outputText id="id" value="#{userdetailsController.selected.id}" title="#{bundle.ViewUserdetailsTitle_id}"/>
</h:outputLink>
<p:tooltip for="id" value="This is your I.D. Number" showEffect="fade" hideEffect="fade" />
<h:outputText value="#{bundle.ViewUserdetailsLabel_username}"/>
<h:outputLink id="username1" value="#">
<h:outputText id="username" value="#{userdetailsController.selected.username}" title="#{bundle.ViewUserdetailsTitle_username}"/>
</h:outputLink>
<p:tooltip for="username" value="Your registered username, this can be changed" showEffect="fade" hideEffect="fade" />
</p:panelGrid>
and here is the not working datatable
<p:dataTable>
<p:column >
<f:facet name="header">
<h:outputText value="{bundle.ViewUserdetailsLabel_id}"/>
</f:facet>
<h:outputText value="{userdetailsController.selected.id}" />
</p:column>
<p:column headerText="username" >
<f:facet name="header">
<h:outputText value="{bundle.ListUserdetailsTitle_username}"/>
</f:facet>
<h:outputText value="{userdetailsController.selected.username}" />
</p:column>
</p:dataTable>
as you can see the outputText values are the same so it should work right ?
thanks
If you happen to have only few hardcoded values to display in a form of a table, then you are better off using <h:panelGrid>. If you however have a list of objects that you want to iterate over and display them quickly then use <p:dataTable>.
Let's say we have a List of employees
<p:dataTable var="employee" value="#{tableBean.employees}">
<p:column headerText="Name">
<h:outputText value="#{employee.name}" />
</p:column>
<p:column headerText="Age">
<h:outputText value="#{employee.age}" />
</p:column>
<p:column headerText="Sex">
<h:outputText value="#{employee.sex}" />
</p:column>
</p:dataTable>
then your table would look like this. var in this case is completely arbitrary, you could for instance call it 'fluffy' if you wanted. There are a lot of settings you can use with dataTable like pagination, export, sorting etc. But I suggest you familiarize yourself with Primefaces showcase

Resources