Clear input validation error from backing bean - jsf

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

Related

Using onclick event to capture the values of cell in a data table -primefaces

I am trying to capture the value of cell in a data table each time the user clicks it and update the same in a textbox. I referred this primefaces showcase url: https://www.primefaces.org/showcase/ui/data/datatable/edit.xhtml
CellEdit event doesn't work for me as I do not want the user to edit the cell and hence have disabled the input text box for the cell.
As there is no event for cell select, how can I make it work using javscript/jquery or anything.
<h:form id="form">
<p:dataTable id="cars2" var="car" value="#{dtEditView.cars2}"
editable="true" editMode="cell" widgetVar="cellCars">
<f:facet name="header">
Cell Editing with Click and RightClick
</f:facet>
<p:ajax event="cellEdit" listener="#{dtEditView.onCellEdit}" />
<p:column headerText="Id">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{car.id}" />
</f:facet>
<f:facet name="input">
<p:inputText id="modelInput" value="#{car.id}" disabled="true"
style="width:96%" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Year">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{car.year}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{car.year}" disabled="true"
style="width:96%" label="Year" />
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
<p:contextMenu for="cars2" widgetVar="cMenu">
<p:menuitem value="Edit Cell" icon="ui-icon-search"
onclick="PF('cellCars').showCellEditor();return false;" />
<p:menuitem value="Hide Menu" icon="ui-icon-close"
onclick="PF('cMenu').hide()" />
</p:contextMenu>
</h:form>
This is where I want the cell values to get updated as soon as the user clicks on any cell. This textarea is present in the same form as the data table.
<p:panel style="width:56%;height:56%;">
<p:inputTextarea id="notesTextArea" value="#{tree.result}"/>
</p:inputTextarea>
</p:panel>
Please help.

JSF enable/disable commandLink depending on filling two inputText and boolean flag without javaScript

I am trying to enable/disable a commandLink depending more than one condition.
At the beginning the commandLink is disabled. To enable it, I must click on a commandButton that activates a boolean flag (this point is currently working) and two inputText must be filled.
CommandLink:
<p:commandLink id="buttonGuardar" action="#{vinculacionesGestionDetalleController.buttonGuardar}" update="#form" process="#form" styleClass="fa-commandlink fa-floppy-o" immediate="true" disabled="#{vinculacionesGestionDetalleController.flagGuardar and empty vinculacionesGestionDetalleController.vinculacionLaboral.denominacionCas and empty vinculacionesGestionDetalleController.vinculacionLaboral.denominacionVal}">
<h:outputText value="#{msg.guardar}" />
</p:commandLink>
commandButton that returns a boolean flag from the controller:
<p:commandButton id="validacionesValidarCodigoButton" actionListener="#{vinculacionesGestionDetalleController.buttonValidar}" value="Validar" styleClass="searchButton" icon="fa fa-button fa-check-circle" process="#form" style="margin-left: 20px;" update="buttonGuardar">
</p:commandButton>
inputText:
<p:row>
<p:column styleClass="alignTextRight">
<h:outputLabel value="#{msg.vinculaciones_gestion_detalle_denominacionCas}" for="inputDenominacionCas" />
</p:column>
<p:column>
<p:inputText id="inputDenominacionCas" style="width:100%" value="#{vinculacionesGestionDetalleController.vinculacionLaboral.denominacionCas}" />
</p:column>
</p:row>
<p:row>
<p:column styleClass="alignTextRight">
<h:outputLabel value="#{msg.vinculaciones_gestion_detalle_denominacionVal}" for="inputDenominacionVal" />
</p:column>
<p:column>
<p:inputText id="inputDenominacionVal" style="width:100%" value="#{vinculacionesGestionDetalleController.vinculacionLaboral.denominacionVal}" />
</p:column>
</p:row>
As you can see, I have tried using more than two conditions on disable property of commandLink:
disabled="#{vinculacionesGestionDetalleController.flagGuardar and not empty vinculacionesGestionDetalleController.vinculacionLaboral.denominacionCas and not empty vinculacionesGestionDetalleController.vinculacionLaboral.denominacionVal}"
But it is not working.
Firstly, logical operations that in "disabled" attribute are wrong. As I understood, you want to enable the link when flag is true and inputTexts are not empty.
enabled="#{flag and not empty inputText1 and not empty inputText2}"
Oh no, commandLink doesn't have enabled attribute. No problem:
disabled="#{not (flag and not empty inputText1 and not empty inputText2)}"
Now the changes at the values of inputTexts must trigger an ajax event that will update the commandLink.
<p:row>
<p:column styleClass="alignTextRight">
<h:outputLabel value="#{msg.vinculaciones_gestion_detalle_denominacionCas}" for="inputDenominacionCas" />
</p:column>
<p:column>
<p:inputText id="inputDenominacionCas" style="width:100%" value="#{vinculacionesGestionDetalleController.vinculacionLaboral.denominacionCas}" >
<p:ajax event="keyup" update="buttonGuardar"/>
</p:inputText>
</p:column>
</p:row>
<p:row>
<p:column styleClass="alignTextRight">
<h:outputLabel value="#{msg.vinculaciones_gestion_detalle_denominacionVal}" for="inputDenominacionVal" />
</p:column>
<p:column>
<p:inputText id="inputDenominacionVal" style="width:100%" value="#{vinculacionesGestionDetalleController.vinculacionLaboral.denominacionVal}" >
<p:ajax event="keyup" update="buttonGuardar"/>
</p:inputText>
</p:column>
</p:row>
If you want ajax event get triggered only when inputText lose focus, you can use "blur" event instead of "keyup".

Primefaces autocomplete as a datatable filter

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>

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.

Resources