There's a datatable with a h:selectOneMenu in each row. I want to be able to retrieve the value selected in the selectOneMenu in the bean. I'm using richfaces a4j:support tag to make AJAX calls to the backing bean. You can see the code below:
DataTable header:
<t:dataTable id="datatable" var="row" value="#{myBean.dataTableRows}">
SelectOneMenu with A4j:
<h:selectOneMenu id="type" label="Type:" styleClass="tamanho80"
value="#{datatableHolder.selectedValue}" converter="comboConverter" immediate="true" >
<f:selectItem itemValue="#{null}" itemLabel="" />
<t:selectItems var="tp"
itemValue="#{tp}" itemLabel="#{tp.nome}"
value="#{row.comboTypeValues}" />
<f:attribute name="row" value="#{row}"/>
<a4j:support event="onchange" reRender="parent" actionListener="${myBean.executeAjax}" immediate="true" ajaxSingle="true" />
</h:selectOneMenu>
The Backing Bean method to be executed:
public void executeAjax(ActionEvent event){
ValueHolder comboBox = (ValueHolder) event.getComponent().getParent();
comboBox .getValue();
}
comboBox .getValue() is returning NULL, even when I select a value.
PS:
This question has been identified as a possible duplicated of this question, but it's not. My question uses a dataTable and doesn't use binding for each element. Also, I'm using JSF 1.1 and RichFaces 3.3.3.
The problem was identified:
Each "option" generated by the t:selectItems tag was with the item id instead of an index, while the comboConverter was using an index to select the item. So, the list had 12 items (indexes should range from 0 to 11), but the id of the selected item was 22 for example. Then the converter would traverse the list to the index 22 and retrieve the element. However there's not such index in this list, because the max value is 12 and then the converter would always return NULL.
For this problem there are basically 3 ways to solve:
Create a new converter that look for the item by it's id
Adapt/Change the "comboConverter" to look for the item by it's id (doing that so, would impact other pieces of code that use this converter
Adapt the list to use indexes instead of ids
I've chosen the first one, due to the minor impact in the system.
Related
I can validate a p:selectOneMenu like this:
<p:selectOneMenu id="eventTimezoneDropdown"
value="#{myBean.eventTimeZone}"
required="true"
requiredMessage="The TimeZone must be specified."
effect="none">
<f:selectItems value="#{myBean.timeZoneItems}"/>
</p:selectOneMenu>
Conceptually speaking, using a p:dataTable with single row selection will achieve the same goal - it allows you to select one row using a selection attribute instead of value attribute and using value attribute instead of <f:selectItems>.
<p:dataTable id="ActivitiesTable" var="row"
value="#{myBean.rows}"
selection="#{myBean.selectedRow}"
rowKey="#{row.activityId}">
<p:column selectionMode="single"/>
...
</p:dataTable>
However I don't see any validation options (e.g. a required attribute) on the p:dataTable.
Is there a way or workaround to have a required selection validation on a p:dataTable similar to the required attribute on p:selectOneMenu?
Environment: Primefaces 5.3, JSF 2.2.8-14, Tomcat 7.0.68.
what i know in primefaces there are not this functionality in datatable, but you can play with your code,
i suggest that you can do the same event in your ManagedBean, so you can check if a row is selected or not, if yes then ok else you can create a simple message, that notifie the user that the selection of a row is required like that:
public void requiredSelect() {
if (myObject == null) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
FacesMessage.SEVERITY_ERROR, "Error", "My object is required!"));
}
}
Another way to work around this issue is by using a hidden input field, bound to the same value which gets updated on row select.
<p:dataTable id="ActivitiesTable" var="row"
value="#{myBean.rows}"
selection="#{myBean.selectedRow}"
rowKey="#{row.activityId}">
<p:ajax event="rowSelectRadio" update="#parent:hiddenTimezoneInput"
<p:column selectionMode="single"/>
...
</p:dataTable>
<h:inputHidden id="hiddenTimezoneInput" value="#{myBean.selectedRow}"
required="true" requiredMessage="The TimeZone must be specified."/>
This way, you can add regular validators on the inputHidden (such as required) and have it processed on form submit.
In a basic registration screen (with button register records the screen) there are two panels:
Data panel:
Address panel:
I can register by completing only the Data panel. It is not necessary to fill the Address panel. However, if at least one field of the Address panel is filled, then all other fields in the same panel should be required.
How can I achieve this?
You need to check in the required attribute if the other inputs have submitted a non-empty value. Since this can result in quite some boilerplate, here's a kickoff example with only 3 input components.
<h:form id="form">
<h:inputText id="input1" value="#{bean.input1}" required="#{empty param['form:input2'] and empty param['form:input3']}" />
<h:inputText id="input2" value="#{bean.input2}" required="#{empty param['form:input1'] and empty param['form:input3']}" />
<h:inputText id="input3" value="#{bean.input3}" required="#{empty param['form:input1'] and empty param['form:input2']}" />
</h:form>
An alternative is to bind the components to the view and use UIInput#getValue() to check the value of the previous components and UIInput#getSubmittedValue() to check them for next components (components are namely processed in the order as they appear in the component tree). This way you don't need to hardcode client ID's. You only need to ensure that binding names doesn't conflict with existing managed bean names.
<h:inputText binding="#{input1}" value="#{bean.input1}" required="#{empty input2.submittedValue and empty input3.submittedValue}" />
<h:inputText binding="#{input2}" value="#{bean.input2}" required="#{empty input1.value and empty input3.submittedValue}" />
<h:inputText binding="#{input3}" value="#{bean.input3}" required="#{empty input1.value and empty input2.value}" />
You'll understand that this produces ugly boilerplate when you have more and more components. The JSF utility library OmniFaces has a <o:validateAllOrNone> validator for the exact purpose. See also the live demo. Based on your quesiton tags, you're using OmniFaces, so you should already be set with just this:
<o:validateAllOrNone components="input1 input2 input3" />
<h:inputText id="input1" value="#{bean.input1}" />
<h:inputText id="input2" value="#{bean.input2}" />
<h:inputText id="input3" value="#{bean.input3}" />
First you should add a method to backing bean something like this:
public boolean isAddressPanelRequired() {
// Check if at least one field is entered
// and return true if it is and false othervise
}
Each input element on address panel should have required="#{backingBean.addressPanelRequired}"
Then add onblur ajax listener on each input component on address panel which process that component, and updates address panel.
I have a datatable with a filter
The filter work good but the result of filter doesn't work. I call ajax inside of p:inputText to try to refresh the result but doesn't work
<h:outputText value="Result"/><h:outputText id="sizeFilterMyWork" value="#{caseManagement.myWork.size()}" />
<h:outputText value="Filter" id="myCaseOutputTextSearch" />
<p:inputText id="globalFilter" onkeyup="PF('myCaseTable').filter()" style="width:150px" >
<p:ajax event="keyup" update="sizeFilterMyWork" listener="#{caseManagement.getSizefilteredMyWork}"></p:ajax>
</p:inputText>
In the bean I have the list of myWork (with get and set) and a list used for the filter (with get and set), when the page is load the result call the size of the list of my work, then, when I use the filter the datatable is shrinking (so it's work) but the number of result doesnt change. Ajax should call the method getSizefilteredMyWork and update the result but doesnt work
Bean
private List<Case> myWork = new ArrayList<Case>(); // get and set
private List<Case> filteredMyWork; //get and set
public int getSizefilteredMyWork(final AjaxBehaviorEvent event)
{
return filteredMyWork.size();
}
How can I fix it?
Your listener method's return value is ignored but you don't need it because the outputText will get its value directly from myWork. It should get the size of the filteredMyWork list instead.
You could try replacing the ìnputText p:ajax with one in the p:datatable:
<p:ajax event="filter" process="#this" update="sizeFilterMyWork" />
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));
}
}
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?