Creating Dropdown Box using AJAX with JSF/Primefaces - ajax

I am trying to create a simple dropdown box using Ajax and JSF 2.0/primeface. Based on First Dropdown selection second dropdown box is populated using AJAX call.
When I select first drop down it correctly populated the second dropdown box based on the Ajax call. But When I make selection in the second dropdown and click the button {which basically submit the form for some action}, It give error message
"formViewBusinessCode:selectedBusinessCode: Validation Error: Value is not valid"
When I check in console that is says the value for "selectedBusinessCode"{Id of second dropdown} is null. I am puzzled becuase it populates correctly but only after selection it gives error that value is not valid (basically null), Why the selected value is not reaching to the bean? Can someone please point what I am missing here, TIA
xhtml code is as below
<h:outputText styleClass="outputText" value="#{constant.businessCodeGroup}"></h:outputText>
<h:selectOneMenu id="selectedBusinessCodeGroup" value="#{viewBusinessCodeBean.selectedBusinessCodeGroup}" >
<f:selectItem itemValue="SELCT" itemLabel="Select Business Code Group" />
<f:selectItems value="#{viewBusinessCodeBean.businessCodeGroupList}" />
<p:ajax listener="#{viewBusinessCodeBean.getOnlyBusinessCodeListByAjaxCall}" event="change" update="selectedBusinessCode" process="#this"/>
</h:selectOneMenu>
<h:outputText styleClass="outputText" value="#{constant.businessCode}"></h:outputText>
<h:selectOneMenu id="selectedBusinessCode" value="#{viewBusinessCodeBean.selectedBusinessCode}">
<f:selectItem itemValue="SELCT" itemLabel="Select Business Code" />
<f:selectItems value="#{viewBusinessCodeBean.businessCodeList}" itemLable="#{viewBusinessCodeBean.businessCodeList.getlable}"
itemValue="#{viewBusinessCodeBean.businessCodeList.getValue}" />
</h:selectOneMenu>
<h:commandButton value="View" action="#{viewBusinessCodeBean.getOnlyBusinessCodeDescription}"></h:commandButton>
The bean coding is as below. it is a #ManagedBean
To Populate First Dropdown box
public ViewBusinessCodeBean() {
logger.entering(CLASS_NAME);
this.businessCodeGroupList = new ArrayList<SelectItem>();
List<String>tempBusinessCodeList = new BusinessCodeTableServices().getBusinessCodeGroupList();
Iterator<String>iterator = tempBusinessCodeList.iterator();
while(iterator.hasNext()){
String businessCodeGroup = iterator.next();
logger.debug(businessCodeGroup);
SelectItem item = new SelectItem(businessCodeGroup);
businessCodeGroupList.add(item);
}
logger.exiting(CLASS_NAME);
}
Ajax Call Method which populated second dropdown
public void getOnlyBusinessCodeListByAjaxCall() {
this.businessCodeList = new ArrayList<SelectItem>();
List<String>tempBusinessCodeList = new BusinessCodeTableServices().getOnlyBusinessCodeList(getSelectedBusinessCodeGroup());
Iterator<String>iterator = tempBusinessCodeList.iterator();
while(iterator.hasNext()){
String businessCode = iterator.next();
SelectItem item = new SelectItem(businessCode,businessCode,businessCode);
businessCodeList.add(item);
}
}

Your bean is apparently in the request scope. A request scoped bean is reconstructed on every request with all properties set to default. Your validation error is caused because businessCodeList property has become null/empty during the request of processing the form submit.
Putting the bean in the view scope should fix this problem.
See also:
Validation Error: Value is not valid
How to choose the right bean scope?

Related

Submit empty value to bean anyway on input with required="true"

I've the below input with required="true":
<p:inputText value="#{bean.value}" required="true">
<p:ajax event="change" listener="#{bean.change()}" />
</p:inputText>
When user changes the value, the listener is fired and I can access the changed value. When user empties the field, the listener is not fired and the empty value is not updating in my bean. I gather that this is caused by requried="true". I would like to update my bean with empty value and fire the listener anyway when the user empties the field. How can I achieve this?
You can just use expression language (EL) in the required attribute too. You can then just check if the main submit button of the form has been pressed. Imagine that your form has a "Save" button like below,
<p:inputText ... required="true">
<p:ajax ... />
</p:inputText>
...
<p:commandButton ... action="#{bean.save}" />
Then you can let the required attribute evaluate true only if the button is invoked. You can achieve that by referencing the component via binding and checking if its client ID is present in the HTTP request parameter map:
<p:inputText ... required="#{not empty param[save.clientId]}">
<p:ajax ... />
</p:inputText>
...
<p:commandButton binding="#{save}" ... action="#{bean.save}" />
Note that #{save} is as-is and may absolutely not be bound to a backing bean, and that the variable name must be unique in the current view and EL scope.
See also:
How to let validation depend on the pressed button?
The issue is that if the user clears the required input field then 'required' validator throws an exception and bean setter will not be called. When the form is reloaded then cleared value will show up again from the bean. Here is my workaround:
public String getSomething() {
return isFormValueEmpty("form:something") ? null : this.something;
}
private Boolean isFormValueEmpty(String formFieldName) {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
String formValue = ec.getRequestParameterMap().get(formFieldName);
logger.debug("Check if form value is empty: [{}] [{}]", formFieldName, formValue);
return StringUtils.isEmpty(formValue);
}

Execute Backing Bean Action on p:selectOneRadio

I'm using a radio component on which, when selecting an item I want to execute an action on backing bean (not navigate to an outcome page, but to perform some action and then update current page via Ajax). Problem is I can't get the backing bean value change listener action to execute
<h:form id="one-radio">
<p:selectOneRadio layout="grid"
valueChangeListener="#{myBean.selectRadioItem}" >
<p:ajax process="#this" update="#form" />
<f:selectItems value="#{myBean.radioOptions}" var="radio"
itemLabel="#{radio.name}" itemValue="#{radio.id}" >
</f:selectItems>
</p:selectOneRadio>
</h:form>
and the backing bean method...
public void selectRadioItem(ValueChangeEvent event) {
String[] selectedItems = (String[]) event.getNewValue();
//more...
}
is there something wrong in the code which I'm missing? I've used this same structure for select many check box which is working...
Rodrigo, there's a difference between valueChangeListener and a simple method call via ajax.
Check this answer by BalusC about the difference between valueChangeListener and <f:ajax>
To solve your problem, you could use the listener property of <p:ajax>.
OneRadio component is used to receive only one value, if you want to select a list of values, use SelectOneMenu
Try to do the following:
<p:selectOneRadio layout="grid" value="#{myBean.radioValue}">
<p:ajax process="#this" update="#form" listener="#{myBean.selectRadioItem}"/>
<f:selectItems value="#{myBean.radioOptions}" var="radio"
itemLabel="#{radio.name}" itemValue="#{radio.id}" >
</f:selectItems>
</p:selectOneRadio>
In the backbean, you can remove the event parameter, because the value of the OneRadio component now is a property, which I named as radioValue
String radioValue;
...
public void selectRadioItem() {
String selectedItem = this.radioValue;
//more...
}

How to skip validation for ajax call?

I have an h:inputText, h:selectonemenu and commandbuton. Inputtext is mandatory field and I have defined it as immediate="true". Then I when I click the button I want to pass current value of selectonemenu to managed bean. But its passig null. How can I manage this validation so that it allows me to get the value of selectOneMenu in Managed bean..
My code is..
<h:inputText id="inputSome" required="true" requiredMessage="Pls enter something"/>
<h:message for="inputSome"></h:message>
<h:selectOneMenu id="recepients" value="#{controller.selected}" immediate="true">
<f:selectItem itemLabel="Select" itemValue=""/>
<f:selectItems value="#{controller.tempNameList1}"></f:selectItems>
</h:selectOneMenu>
<p:commandButton value="Add" action="#{controller.submit}"
immediate="true"/>
When you put immediate=true in the commandButton, then Invoke Application phase is directly executed skipping the phases after (and including) validations. So "applying model values" phase is also skipped and the properties of managed bean are remained uninitialized. This causes you passing null for the value of selectOneMenu. The solution is, you have to retrieve the value for selected property of the controller manually, like bellow:
Map<String, String> paramMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
for (String key : paramMap.keySet()) {
if (key.contains("recepients")) {
selected = Integer.parseInt(paramMap.get(key));
}
}

strange jsf panelgroup binding -> h:selectOneMenu validation Exception

lets start simple:
- an easy search form
- two h:selectOneMenu components are declared inside a form
- the second selectOneMenu, is refreshed base on selecting an item of the first selectOneMenu (with ajax)
For this, i use a central Bean in request scope, because the two selectOneMenus are declared on many other pages, so i dont need to define the two following methods multiple times:
pageSupport:
#SuppressWarnings("unchecked")
public List<BranchenRubrik> getLst_branchenRubrik() {
if(lst_branchenRubrik == null) {
Session session = hibernate.InitSessionFactory.getInstance().getCurrentSession();
Transaction tx = session.beginTransaction();
this.lst_branchenRubrik = session.createQuery("from BranchenRubrik").list();
tx.commit();
}
return lst_branchenRubrik;
}
// Loading Subkats with parameter
#SuppressWarnings("unchecked")
public List<BranchenRubrikSub> getBranchenRubrikSub(long p_parent) {
List<BranchenRubrikSub> lst_branchenRubrikSub = new ArrayList<BranchenRubrikSub>();
if(p_parent > 0) {
Session session = hibernate.InitSessionFactory.getInstance().getCurrentSession();
Transaction tx = session.beginTransaction();
lst_branchenRubrikSub = session.createQuery("from BranchenRubrikSub BRS WHERE BRS.parentRubrik.id = :p1").setLong("p1",p_parent).list();
tx.commit();
}
return lst_branchenRubrikSub;
}
VDL:
<p:selectOneMenu value="#{searchBean2.fvz.branchenRubrikID}">
<f:selectItem itemLabel="Bitte wählen" itemValue="0"/>
<f:selectItems value="#{pageSupport.lst_branchenRubrik}" var="rubrik" itemValue="#{rubrik.id}" itemLabel="#{rubrik.rubrik}"/>
<f:ajax render="uiBranchenSubKat"/>
</p:selectOneMenu>
<h:outputText value="Unterkategorie" />
<p:selectOneMenu id="uiBranchenSubKat" value="#{searchBean2.fvz.branchenRubrikSubID}">
<f:selectItems value="#{pageSupport.getBranchenRubrikSub(searchBean2.fvz.branchenRubrikID)}" var="brs" itemLabel="#{brs.rubrik}" itemValue="#{brs.id}"/>
</p:selectOneMenu>
this works fine, i can submit the form and all data are saved and will be re-displayed.
Now, i want to include an h:panelGroup with binding to a methode, which build a pagination menue.
If i include the h:panelGroup binding="#{searchBean2.paginationMenu}"/> then, i cant submit the form, because it says that the value for the second h:selectOneMenu is not valid.
if i remove the "h:panelGroup binding" all working as expected.
The h:panelgroup can also binded to an empty methode "return new HtmlPanelGroup()"
then, the error occurs again.
looks like, that the component binding, breaks some validation.
thanks for your time

Multiple onClick events

I have a JSF page, a drop down where values are getting fetched from service.
Default is "Select from Drop Down" and a datePicker and a submit button.
I need to apply JS/AJAX validation here.
If a user clicks on Submit button without chosing any value from the drop down and the date. It should first diplay a message,
1) If none chosen, first show a message - Please select a value from drop down.
2) if the value is selected from the drop down and date has not been selected It should display a message " select a date".
3) if the date is selected and value is not selected from the drop down It should display a message " select a value from the drop down".
Both validation should be done on a single click on submit button.
Currently it's just checking if date is not selected. onclick event code is mentioned below.
Drop Down
<h:selectOneMenu id="valueList" value="#bean.values">
<f:selectItem itemValue="Select Action" itemLabel="Select Action" />
<f:selectItems value="#{sampleService.sampleMethod}"
var="SampleVar" itemValue="#{SampleVar}"
itemLabel="#{SampleVar}">
</f:selectItems>
</h:selectOneMenu>
Submit button
<ui:define name="actions">
----h:inputHidden id="getAllDates"
value="#{serviceMethod.getAllDates}"-----
<h:commandButton styleClass="inputbutton" valuGenerate" id="export"
action="#{generate.someReport}" onclick="saveDate(); />
</ui:define>
Passing all selected dates in hidden.
OnClick event this js function is written in another file.
onclick="saveDate();"
function saveDate() {
var dates = $('#selectDates').datepick('getDate');
var datesValue = '';
if(dates==null || dates=="undefined"){
alert("Select Dates");
return false;
}
if(dates!=null){
// store in an array and return true
}
Currently page is getting refreshed on every click on Submit button and alert message gets displayed only for date.
Can anybody help me in applying ajax call on submit button and displaying validation messages?
You're thinking too much in the JavaScript direction. Use JSF provided facilities. Use the required attribute to specify required inputs. Use requiredMessage attribute to specify the validation message. Use <h:message> to display the validation messages. Use <f:ajax> to submit (and validate) data by ajax.
So, this should do:
<h:selectOneMenu id="action" binding="#{action}" value="#{bean.action}" required="true" requiredMessage="Please select action">
<f:selectItem itemValue="#{null}" itemLabel="Select Action" />
<f:selectItems value="#{bean.actions}" />
<f:ajax execute="#this" render="actionMessage date" />
</h:selectOneMenu>
<h:message id="actionMessage" for="action" />
<x:yourDatePickerComponent id="date" value="#{bean.date}" required="#{not empty action.value}" requiredMessage="Please select date">
<f:ajax execute="#this" render="dateMessage" />
</x:yourDatePickerComponent>
<h:message id="dateMessage" for="date" />
(I have no idea what component you're using as date picker, just replace x:yourDatePickerComponent accordingly)
you don't need ajax :
function save() {
var validated = true;
var dates = $('#selectDates').datepick('getDate');
var datesValue = '';
var message;
if(dates==null || dates=="undefined"){
alert("Select Dates");
message = "message1";
validated = false;
return false;
}
if( $('#idOfDropDown').val() != ''){
message = "message2";
validated = false;
return false;
}
if(!validated){
// preveent thr form from submitting
return false;
}
}

Resources