JSF selectOneMenu validation and ajax rendering - ajax

I have a validation on my selectOneMenu to prevent the user to select "None" item in the list.
<h:selectOneMenu id="selectMenu" value="#{bean.selectedValue}" required="true" requiredMessage="Please select an item">
<f:ajax render="toRender selectMenuMessage" listener="#{bean.onSelect}"/>
<f:selectItem itemLabel="None" noSelectionOption="true"/>
<f:selectItems value="#{bean.items}" var="item" itemValue="#{item.id}" itemLabel="#{item.label}"/>
</h:selectOneMenu>
I have my panel below and a want to show it only when my item is not "None".
So when I select "None", the message should render and the panel disappear.
<h:panelGroup id="toRender">
<h:panelGrid rendered="#{bean.selectedValue == 0 ? false : true">
...
</h:panelGrid>
</h:panelGroup>
It's working without the validation but I can't make both work.. It's like if validation prevents rendering.
Any suggestion?
Thanks

I guess that bean.selectedValue is an Integer, so try this:
<f:selectItem itemValue="0" itemLabel="None" noSelectionOption="true"/>
Edit:
Ah sorry, I think misunderstood your problem a little bit.
The problem here is, that if you are requiering a value for the selectOneMenu the value will not submitted if it is empty. And if the item with noSelectionOption="true" is selected, it will be handled as empty, so no value will be submitted. When you are checking against bean.selectedValue == 0, selectedValue will never - except maybe initially - be 0, because when you select the item with value 0 it will not be submitted, as described above.
So you are right, your validation and the check for bean.selectedValue == 0 can not work together. I would recommend you to just remove the validation.
If this is no option for you, please explain me why you need it to work that way in more details.

I have a response, it's not the solution but it's another way to do this...
<h:selectOneMenu id="selectMenu" value="#{bean.selectedValue}">
<f:ajax render="toRender selectMenuMessage" listener="#{bean.onSelect}"/>
<f:selectItem itemLabel="None" noSelectionOption="true"/>
<f:selectItems value="#{bean.items}" var="item" itemValue="#{item.id}" itemLabel="#{item.label}"/>
</h:selectOneMenu>
And in the bean
public void onSelect() {
if(this.selectedValue != 0) {
// Do smthg here
} else {
// Display error message
UIComponent component = Outils.getFacesContext().getViewRoot().findComponent(":form:selectMenu");
if(component != null) {
Outils.getFacesContext().addMessage(component.getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, "", "Test msg"));
}
}
}
This way the validation process is not launched and the verification is done in the bean.
If someone find something better, let me know!

Related

<p:spinner> max value won't change anymore into other value after getting error validation form [duplicate]

This question already has answers here:
How can I populate a text field using PrimeFaces AJAX after validation errors occur?
(3 answers)
How to reset input fields in a form after validation fail when updating it with new values
(2 answers)
Closed 3 years ago.
So, it worked fine, until it get error required validation in form. myMaxDuration won't change anymore in xhtml, but when I sysout it in console it changed.
If, the myMaxDuration I send into bean is 30, Ajax worked fine.
But, if myMaxDuration when I send into bean is 10, ajax won't work.
already tried using ajax update in bean
<p:panelGrid columns="1" columnClasses="ui-grid-col-6" layout="grid" styleClass="ui-panelgrid-blank">
<p:outputLabel value="Name"/>
<p:inputText value="#{myBean.nEmp.name}" required="true"/>
<p:outputLabel value="Status" styleClass="labelSmall"/>
<p:selectOneMenu required="true" value="#{myBean.nEmp.employmentStatusID}"
<f:selectItem itemValue="10" itemLabel="10"/>
<f:selectItem itemValue="20" itemLabel="20"/>
<f:selectItem itemValue="30" itemLabel="30"/>
<p:ajax listener="#{myBean.maxDuration()}" update=":form:durasiID"></p:ajax>
</p:selectOneMenu>
</p:panelGrid>
<p:outputPanel>
<p:panelGrid columns="1" columnClasses="ui-grid-col-3" layout="grid" styleClass="ui-panelgrid-blank" rendered="#{myBean.nEmp.employmentStatusID != 6}">
<p:outputLabel value="Durasi" styleClass="labelSmall"/>
<p:spinner min="1" max="#{myBean.myMaxDuration}" id="durasiID" value="{myBean.nEmp.monthDuration}"/>
</p:panelGrid>
</p:outputPanel>
<p:commandButton value="save" action="#{myBean.saveNewDecreeEmployee()}" />
on my bean
public void maxDuration() {
if(nEmp.getEmploymentStatusID() == 10) {
myMaxDuration = 10;
}
else if(nEmp.getEmploymentStatusID() == 20) {
myMaxDuration = 20;
}
else {
myMaxDuration = 30;
}
nEmp.setMonthDuration(myMaxDuration);
System.out.println(myMaxDuration + " - maxDuration");
}
the value of in xhtml should be changed like in console, after someone get error form validation field name required.
So, I solved this problem by reference of #Kukeltje
Based on this, How can I populate a text field using PrimeFaces AJAX after validation errors occur?
I just add resetValues="true" into my <p:ajax>
and it's worked fine.

How to Trigger Ajax To Load Nested Dropdowns After Loading A Form?

I have a button to display an edit dialog form with a selectOneMenu that holds prefix number values in it and, after selecting one of those prefix values, three selectCheckboxMenu are loaded with employees data. This is workinkg fine.
<p:outputLabel value="prefix" for="prefixo" />
<h:panelGroup>
<p:selectOneMenu id="prefixo" value="#{demandasController.selected.prefixo}" converter="prefixosConverter" filter="true" filterMatchMode="contains">
<f:selectItem itemLabel="#{adeBundle.SelectOneMessage}" itemValue="#{null}" />
<f:selectItems value="#{prefixosController.items}"
var="prefixoItem"
itemValue="#{prefixoItem}"
itemLabel="#{prefixoItem.prefixo} - #{prefixoItem.nomePrefixo}"
/>
<p:ajax event="valueChange" update="uorPosCollection uorPosCollection1 uorPosCollection2" listener="#{demandasController.changePrefixo}"/>
</p:selectOneMenu>
</h:panelGroup>
<p:outputLabel value="Executivo(s)" for="uorPosCollection" />
<p:selectCheckboxMenu id="uorPosCollection" value="#{demandasController.selected.uorPosCollection}" label="Executivo(s)" multiple="true" converter="uorPosConverter" filter="true" filterMatchMode="contains" >
<f:selectItems value="#{demandasController.availableExecutivos}"
var="uorPosCollectionItem"
itemValue="#{uorPosCollectionItem}"
itemLabel="#{uorPosCollectionItem.matricula} - #{uorPosCollectionItem.nome} (#{uorPosCollectionItem.prefixo.prefixo})" />
</p:selectCheckboxMenu>
<!-- analogous code ommited -->
The Listener:
public void changePrefixo(AjaxBehaviorEvent event) {
availableExecutivos = LoadExecutivosListCombo(super.getSelected().getPrefixo());
//analogous methods ommited
}
The methods to load the employees lists:
private List<UorPos> LoadExecutivosListCombo(Prefixos prefixos) {
List<SelectItem> listExecutivosCombo = new ArrayList<>();
List<UorPos> listExecutivos = uorPosFacade.findUorPosExecutivosByPrefixo(prefixos);
for (int i = 0; i < listExecutivos.size(); i++) {
listExecutivosCombo.add(new SelectItem(listExecutivos.get(i)));
}
return listExecutivos;
}
//analagous methods ommited
Native queries to retrieve database:
public List<UorPos> findUorPosExecutivosByPrefixo(Prefixos prefixo) {
return (List<UorPos>) getEntityManager().createNativeQuery("SELECT * FROM UorPos WHERE prefixo=9951", UorPos.class).setParameter(1, prefixo.getPrefixo()).getResultList();
}
//analagous methods ommited
But when editing a register that already has prefix and employee values (saved earlier by some user), the 3 selectCheckboxMenu are loaded showing (undesired) id's entity class name on its labels value and empty dropdowns:
e.g.: in the figure above, when the edit form was loaded, it shows the values saved earlier by some user: the prefix 9882 (displayed as expected) and the three (empty) dropdowns for employees (displayed with the undesired class names in it). If I select a different value than 9882, the dropdowns are (ajax) filled as expected and if I select 9882 again, the employees are displayed as expected (without the class names):
I'm trying to resolve it by activating the ajax as below, but don't know how to call it in the function:
<p:dialog onShow="CallAjaxFunction()" modal="true" >
<script>
function CallAjaxFunction() {
<!-- how to call the ajax here ? -->
alert("displaying after form was loaded.")
}
</script>
...
</p:dialog>
Does anyone knows how to trigger ajax to load nested dropdowns after loading a form?
Or if someone has any other solution to display the values in the labels (without the class name) and automattically load the nested dropdowns, I appreciate that.
Thanks in advance.
After researching, I've used the listener to update the combos, using for this the open ajax event in the dialog:
<p:dialog onShow="PF('prefixowv').selectValue(':selected').click();" update= DemandasEditForm:uorPosCollection DemandasEditForm:uorPosCollection1 DemandasEditForm:uorPosCollection2 />
And changed the ajax event to selectItem, instead of valueChange:
<p:selectOneMenu id="prefixo" value="#{demandasController.selected.prefixo}" converter="prefixosConverter" filter="true" filterMatchMode="contains">
<f:selectItem itemLabel="#{adeBundle.SelectOneMessage}" itemValue="#{null}" />
<f:selectItems value="#{prefixosController.items}"
var="prefixoItem"
itemValue="#{prefixoItem}"
itemLabel="#{prefixoItem.prefixo} - #{prefixoItem.nomePrefixo}"
/>
<p:ajax event="selectItem" update="uorPosCollection uorPosCollection1 uorPosCollection2" listener="#{demandasController.changePrefixo}"/>
</p:selectOneMenu>
Regards,

h:commandButton's onclick JavaScript method dosen't run before Submitting the form

hello all.I'am new to jsf.
Now i know that to set the Managed Bean attributes i can use forms, But i'm using JavaScript in my jsf page.
what i want is to execute the javascript methode onclickAdd() before submitting the form so the user can see what's changed in an anychart map of tunisia along to a table.
My jsf page have a dropdown list.
<h:form>
Gouvernorats   Temperature (C°) <br/>
<h:selectOneMenu id="list" value="#{GouvBean.name}" >
<f:selectItem itemValue="Tunis" itemLabel="Tunis" />
<f:selectItem itemValue="Médenine" itemLabel="Medenine"/>
<f:selectItem itemValue="Gabès" itemLabel="Gabès"/>
<f:selectItem itemValue="Sfax" itemLabel="Sfax"/>
<f:selectItem itemValue="Sidi Bou Zid" itemLabel="Sidi Bou Zid"/>
<f:selectItem itemValue="Kassérine" itemLabel="Kassérine"/>
<f:selectItem itemValue="Mahdia" itemLabel="Mahdia"/>
<f:selectItem itemValue="Sousse" itemLabel="Sousse"/>
<f:selectItem itemValue="Monastir" itemLabel="Monastir"/>
<f:selectItem itemValue="Tataouine" itemLabel="Tataouine"/>
<f:selectItem itemValue="Kebili" itemLabel="Kebili"/>
<f:selectItem itemValue="Tozeur" itemLabel="Tozeur"/>
<f:selectItem itemValue="Bèja" itemLabel="Bèja"/>
<f:selectItem itemValue="Jendouba" itemLabel="Jendouba"/>
<f:selectItem itemValue="Bizerte" itemLabel="Bizerte"/>
<f:selectItem itemValue="Manubah" itemLabel="Manubah"/>
<f:selectItem itemValue="Ben Arous" itemLabel="Ben Arous"/>
<f:selectItem itemValue="Zaghouan" itemLabel="Zaghouan"/>
<f:selectItem itemValue="Siliana" itemLabel="Siliana"/>
<f:selectItem itemValue="Le Kef" itemLabel="Le Kef"/>
<f:selectItem itemValue="Gafsa" itemLabel="Gafsa"/>
<f:selectItem itemValue="Kairaouan" itemLabel="Kairaouan"/>
<f:selectItem itemValue="Nabeul" itemLabel="Nabeul"/>
</h:selectOneMenu>
<h:inputText id="Temperature" value="#{GouvBean.temperature}" ><f:ajax listener="#{GouvBean.inchange}"/></h:inputText>
<h:commandButton value="+"onclick="onClickAdd();" >
<f:ajax execute="#form"/>
</h:commandButton>
</h:form>
The javascript method changes a table and an AnyChart map:
this is the table:
<table id="myTable">
<thead><tr><th>Gouvernorats</th><th>Temperature</th> </tr></thead>
<tbody></tbody>
</table>
and this is JavaScript method:
//Define a JavaScript method
function onClickAdd(){
//saving the value of the list
var Gov = document.getElementById("list");
var Gid=Gov.options[Gov.selectedIndex];
//deleting the current valye(added value) from the list
Gov.remove(Gov.selectedIndex)
var C°=document.getElementById('Temperature');
//Getting refrence to tbody
var tbodyRef=document.getElementById("myTable").getElementsByTagName("tbody")[0];
//appending a row to tbody
var row=tbodyRef.insertRow(tbodyRef.rows.length);
var cell1=row.insertCell(0);
var cell2=row.insertCell(1);
var cell3=row.insertCell(2);
//Creation of delete button
var del=document.createElement("BUTTON");
var t=document.createTextNode("-");
//Giving value to the cells
cell1.innerHTML=Gid.value;
cell2.innerHTML=C°.value;
cell3.appendChild(del);
//adding a listener to the button
del.appendChild(t);
//OnAddChangeValue(cell1.innerHTML,cell2.innerHTML);
del.addEventListener("click",function(){
//1)knowing the row where the button is(index)
var x=del.parentNode.parentNode.rowIndex;
x=x-1;
//2)moving the value of the first cell back to the list
var l=document.getElementById("list");
//create option node
var node=document.createElement("option");
//create attribute value
var attr1=document.createAttribute("value");
//creation of label
var label=document.createTextNode(tbodyRef.rows[x].cells[0].innerHTML);
//setting a value to the attribute
attr1.value=tbodyRef.rows[x].cells[0].innerHTML;
//linking...
node.setAttributeNode(attr1);
node.appendChild(label);
l.appendChild(node);
//3)deleting the row from the tbody
tbodyRef.deleteRow(x);
// OnDeleteChangeValue(cell1.innerHTML);
});
}
</script>
and this is h:head
<h:head><title>Hello world-JSF-Input Form</title>
</h:head>
help me please
NB: IT WORKS WHEN I ADD h:form before but in this case javascript dont work !
You use ajax in the h:selectOneMenu and h:inputText that sends the values to the server/beans already if they are in an h:form (as you found out). But instead of asking how do I send data without a form (which makes the commandButton 'work'), the question should have been
How do I prevent an h:commandButton from refreshing the page.
For which the answer is given here:
How make commandButton not fully refresh page? How to use f:ajax?
But since you do not seem to need (or even want) to send anything to the server on clicking the (command)Button, a plain non submitting html button with an onClick would be sufficient. This can be achieved by adding type="button" to the h:commandButton (or by using the plain html counterpart which is legal too)
What's exactly is the difference between types of h:commandbutton?
Some more general knowledge:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes
https://www.mkyong.com/jsf2/jsf-2-button-and-commandbutton-example/
After debugging the page in google chrome browser , i found that i need to:
1) include<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.3.15/proj4.js"/>
2) i realized that the id value in jsf is changed in html :
if an id of an element is "list" in jsf it becomes "j_idt6:list" in html.so in getElmentbyid i need to do like this: document.getElementById("j_idt6:list") instead of document.getElementById("list")
now everything work fine.

At least one/group of multiple fields required in JSF

I'm trying to do a search function of which I have multiple fields and need at least one of them required, or a group of them.
The only answer I found on StackOverflow is this one: How to validate if at least one of multiple input fields is entered?
And there are 2 solutions there: One uses Omnifaces (which I can't use due to project requirements), and the other is not elegant, because it grows a lot when the number of fields is big.
I have these fields for example:
<p:selectOneMenu value="#{backingBean.type}"id="type">
<f:selectItem itemLabel="#{constantsController.SELECT_TYPE_HEADER}"
itemDisabled="true" />
<f:selectItems
value="#{constantsController.getTypes().entrySet()}"
var="entry" itemValue="#{entry.key}" itemLabel="#{entry.value}" />
</p:selectOneMenu>
<p:inputText id="number" value="#{backingBean.number}"/>
<p:inputText id="year" value="#{backingBean.year}"/>
<p:inputText id="number2" value="#{backingBean.number2 }"/>
<p:selectOneMenu value="#{backingBean.state}"
id="state" filter="true" filterMatchMode="startsWith">
<f:selectItem itemLabel="Choose its state" disabled="true" />
<f:selectItems value="#{constantsController.getStates().entrySet()}"
var="entry" itemValue="#{entry.key}" itemLabel="#{entry.value}" />
</p:selectOneMenu>
<p:selectOneMenu id="entity"
value="#{backingBean.entity }">
<f:selectItem itemLabel="Select entity"
itemDisabled="true" />
<f:selectItem itemLabel="Entity1" itemValue="1"></f:selectItem>
<f:selectItem itemLabel="Entity2" itemValue="2"></f:selectItem>
</p:selectOneMenu>
<p:selectOneMenu id="documentType"
value="#{backingBean.documentType}">
<f:selectItems
value="#{constantsController.getDocumentTypes().entrySet()}"
var="entry" itemValue="#{entry.key}" itemLabel="#{entry.value}" />
</p:selectOneMenu>
<p:inputText id="documentNumber" value="#{backingBean.documentNumber}"/>
So as you can see, I have multiple fields. And the requirements dictate that I need one of the following required (I'll write the id's):
1- type + number + year
2- number2 + state
3- entity
4- documentType + documentNumber
So I when I click the commandButton, I need this to check if one of these groups (1, 2, 3 or 4) is filled.
Also, the groups in itself need to be required, i.e. let's say I already filled 'entity', and I also filled the 'year', it cannot let me advance since year needs to be accompanied by 'type' and 'number'.
I solved it by associating a boolean in the backing bean to each of the fields/group of fields. It's not an elegant solution, but I wasn't finding any other solution.
So what I did was define by group of fields in the backing bean a boolean initialized with true value:
private boolean typeNumberYear = true;
private boolean number2State = true;
private boolean entityRequired = true;
private boolean documentTypeDocumentName = true;
private boolean masterRequired = true;
then to validate them:
public void checkRequiredFields(){
if(!type.equals("") && number != 0 && year != 0)
typeNumberYear = false;
if(number2 != 0 && !state.equals(""))
number2State = false;
if(!entity.equals(""))
entityRequired= false;
if(!documentType.equals("") && documentNumber != 0)
documentTypeDocumentName = false;
if(!typeNumberYear || !number2State || !entityRequired || !documentTypeName)
masterRequired = false;
}
Since all this is in the backing bean, I can just put this function on the actionListener of the command button, while the action function is still in the controller.
<p:commandButton value="Search" icon="ui-icon-search"
actionListener="#{backingBean.checkRequiredFields}"
action="#{controller.searchButtonClicked}"/>
Now in the required parameter I just associated the respective boolean and the masterRequired on all of them. E.g. in the type, number and year inputs, I put the required as follows:
required = "backingBean.typeNumberYear and backingBean.masterRequired"
The only downside to this solution, is that in the interface, there will be appearing an asterisk on all the fields that are indicated above, but if you just input the entity for example, it will search as it is supposed to, and then it will update and remove the asterisks.

primefaces selectonemenu change event not working for null value

I have a selectonemenu that includes some items. And a null item for showing "please choose one"..
MY goal is to query some data when I select one of them. And if i select the "please choose one" do another thing.
But eventually, the change event is fired for normal values but if I select "please choose one" item , it is not fired. Thanks for your help. Here is my code.
<p:selectOneMenu style="width: 200px" id="positionForward" value="#{hrProcessController.queryCriteria.positionForward}" converter="listConverter"
effect="fade" var="u" filter="true" filterMatchMode="startsWith" validator="#{hrProcessController.isOpenPositionForwValid}">
<f:selectItem itemLabel="#{menu['onemenu.choose']}" itemValue="#{null}"/>
<f:selectItems value="#{hrProcessController.positionList}" var="position" itemLabel="#{position.name}" itemValue="#{position}" />
<p:ajax event="change" listener="#{hrProcessController.onPositionSelect}" update="openPositionForward"/>
<p:column>
<h:outputText value="#{u==null ? menu['onemenu.choose'] : u.name}" />
</p:column>
</p:selectOneMenu>
public void onPositionSelect()
{
if(queryCriteria.getPositionForward()!=null)
{
OpenPositionQueryCriteria criteria = new OpenPositionQueryCriteria();
criteria.setPosition(queryCriteria.getPositionForward());
List<OpenPosition> openPositions = openPositionService.searchOpenPosition(criteria);
setOpenPositionList(openPositions);
}
else
{
List<OpenPosition> positions = openPositionService.getActiveOpenPositionList();
setOpenPositionList(positions);
}
}
If you use itemValue="#{null}" or itemValue="", the valueChangeListener method never will be called.
That's a better approach if you want your first item null:
<f:selectItem
itemDisabled="true"
itemLabel="#{null}"
itemValue="#{null}" />
I had the same problem.
Change event WON'T be fired by selecting default value. Why that is so is beyond me. Such things are normal usually.
I didn't find any real solution.
You should try to write custom validator and converter for this.
Try this:
Using a "Please select" f:selectItem with null/empty value inside a p:selectOneMenu
OK, I finally found the solution to this!
you need to add immediate="true" to ajax call.
Adding immediate tells ajax to ignore any potential validation errors and call the onChange anyway.
Try it.
I was with the same issue so I put the selectItem without the propertie itemValue like that:
<f:selectItem itemLabel="#{menu['onemenu.choose']}" />

Resources