How can I use ajax to submit h:selectOneRadio? - ajax

I'm having a problem getting things to work the way I think they should. I have a dataTable that I'm building from a list of benefits objects. Each of those objects can have one and only one type: group, account, or parent. I want to refresh the list when a radio button is selected. When the page loads, the group objects are displayed and the group radio button is pre-selected. If the user clicks the account radio button, I'm using Ajax to refresh the list, this time presenting Account objects. Here's the stripped down code:
XHTML:
<!-- Radio button to subset records -->
<h:selectOneRadio
id="varButtons"
value="#{benefitUI.buttonValue}"
styleClass="radio">
<f:selectItem
itemLabel="Group"
itemValue="G" />
<f:selectItem
itemLabel="Account"
itemValue="A" />
<f:selectItem
itemLabel="Parent"
itemValue="P" />
<p:ajax event="click" update="benList" process="#this" />
</h:selectOneRadio>
<p:dataTable
id="benList"
var="ben"
value="#{benefitUI.filteredBenefitList}"
rowIndexVar="vbRowIndex"
rowClasses="panel-grid-row-odd, panel-grid-row-even"
styleClass="mimic-datatable"
<p:column headerText="From" style="text-align:center;">
<h:outputText value="#{ben.beginDate}"/>
</p:column>
<p:column headerText="To" style="text-align:center;">
<h:outputText value="#{ben.endDate}"/>
</p:column>
</p:dataTable>
Java for BenefitUI:
#PostConstruct
public void init() {
/* Code that creates my unfiltered list removed for brevity. */
/** benefitList is the name of the unfiltered list **/
// Pre-select group on page load
setButtonValue("G");
}
public List<Benefit> getFilteredBenefitList() {
String filter = getButtonValue();
List<Benefit> filteredList = new ArrayList<Benefit>();
for (Benefit vb : benefitList) {
// The below code is working just fine, when filter is not blank
if ((filter.equals("G") & vb.getGroup() != null)
|| (filter.equals("A") & vb.getAccount() != null)
|| (filter.equals("P") & vb.getParent() != null)) {
filteredList.add(vb);
}
}
return filteredList;
}
public void setButtonValue(String bValue) {
this.buttonValue = bValue;
}
public String getButtonValue() {
return this.buttonValue();
}
The page loads just fine, displaying the group benefits. But when I click the Account button, an empty string is passed to the setButtonValue method, so when the filtered list is built, no records are included, and the page displays an empty list. What am I doing wrong that the itemValue isn't being sent to setButtonValue? Secondarily, why are the setButtonValue and the getFilteredBenefitList methods both being called four times?
I'm sure there's a keyword or something I'm missing, either on the Ajax line or in the selectItem, but I have no idea what it might be.

Related

Selection of extendedDataTable inside popupPanel not in Ajax Request Parameter

I am having a JSF page that contains a modal popupPanel from Richfaces and inside this popupPanel is an extendedDataTable. Now I want to have the user selection in my bean every time the user selects a new row. At first I want to show the code then I will explain the problem.
Part of the xhtml page with the popupPanel and the extendedDatatable:
<rich:popupPanel id="kontaktPanel" modal="true" onmaskclick="#{rich:component('kontaktPanel')}.hide()">
<rich:extendedDataTable
value="#{nachfrageBean.loadedKontakte}" var="kontakt"
selection="#{nachfrageBean.selection}" id="kontaktTable">
<rich:column>
<f:facet name="header">
<h:outputText value="#{messages['tabelle.kontakt.instknz']}" />
</f:facet>
<h:outputText value="#{kontakt.instKnz}" />
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="#{messages['tabelle.kontakt.name']}" />
</f:facet>
<h:outputText value="#{kontakt.name}" />
</rich:column>
<a4j:ajax execute="kontaktTable kontaktPanel" event="selectionchange" listener="#{nachfrageBean.selectedRecord}" />
</rich:extendedDataTable>
</rich:popupPanel>
Corresponding bean with the listener and the needed members:
public class NachfrageBean {
private KontaktDTO kontakt;
private List<KontaktDTO> loadedKontakte = new ArrayList<KontaktDTO>();
/** DOCUMENT ME! */
private Collection<Object> selection;
public Collection<Object> getSelection() {
return selection;
}
public void setSelection( Collection<Object> selection ) {
this.selection = selection;
}
public List<KontaktDTO> getLoadedKontakte() {
//contacts are successfully loaded
return kontaktBusiness.getAllKontakte( );
}
public KontaktDTO getKontakt() {
return kontakt;
}
public void setKontakt( KontaktDTO kontakt ) {
this.kontakt = kontakt;
}
public void selectedRecord( AjaxBehaviorEvent event ) {
UIExtendedDataTable dataTable = ( UIExtendedDataTable )event.getComponent();
Object originalKey = dataTable.getRowKey();
for( Object selectionKey : selection ) {
dataTable.setRowKey( selectionKey );
if( dataTable.isRowAvailable() ) {
// do something with the selection
}
}
dataTable.setRowKey( originalKey );
}
}
The listener gets called successfully when the user selects a row in the datatable, but the selection is null, so I am getting a NPE. And when I remove the popupPanel and have my extendedDatatable directly in my page, then it works fine. I am always printing out the request parameters and I can see that there are two missing parameters when I have the datatable inside the pupupPanel. These request parameters are:
mainForm:kontaktTable:wi =
mainForm:kontaktTable:si = 3,3|3||x
So outside the popup the selection from the kontaktTable gets submitted but inside the popupPanel not. Does anyone know whats wrong here?
I just found a solution here .
By default the rich:popupPanel will be attached to the body and not to the form. Adding domElementAttachment="form" to the popupPanel just did it.

Creating Dropdown Box using AJAX with JSF/Primefaces

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?

Dynamic content inside Ajax's "Update" tag

I am trying to update dynamically the content of the clicked tab inside a tabView in Primefaces. I am trying to simulate what I have inside the listener tag for my ajax, I know this doesn't work when clicking a tab because the EL inside the listener tag has already been evaluated to a string. The question, is there any way to do this?? Thanks for your help.
<p:tabView id="tv1" widgetVar="wv1" activeIndex="1">
<p:ajax event="tabChange"
listener="#{bean.onTabChange}"
update="#{bean.updatedTabID}"/>
<p:tab title="tab1">
<p:dataTable id="dtTab1">... </p:dataTable>
</p:tab>
<p:tab title="tab2">
<p:dataTable id="dtTab2">... </p:dataTable>
</p:tab>
</p:tabView>
Backing bean
String updatedTab
public String updatedTabID(){
return updatedTab;
}
public void onTabChange(TabChangeEvent event) {
Tab activeTab = event.getTab();
String activeTabTitle = activeTab.getTitle();
if(activeTabTitle.equals("tab1")){
updatedTab=":tv1:dtTable1";
// update dataTable1 collection
}else if(activeTabTitle.equals("tab2")){
updatedTab=":tv1:dtTable2";
// update dataTable2 collection
}
}

Text box Rendering in JSF 2.0

I have a text box where the end user has to enter the number of text boxes that should be rendered. Based on the number entered, the number of text boxes have to render dynamically in row-format.
Also in the newly rendered row formatted text boxes the values entered has to be identified with correct backing bean when it goes to the next page.
Any suggestions on where to start or how to achieve something like this?
You can use <h:inputText> to ask enduser for input.
<h:inputText value="#{bean.number}" />
You can use <h:commandButton> to let user submit a form.
<h:commandButton value="Submit" action="#{bean.submit}" />
You can use List<T> to have a collection of items.
private List<Item> items;
public void submit() {
items = new ArrayList<Item>();
for (int i = 0; i < number; i++) {
items.add(new Item());
}
}
You can use <h:dataTable> to present it in rows.
<h:dataTable value="#{bean.items}" var="item">
<h:column>
<h:inputText value="#{item.value}" />
</h:column>
</h:dataTable>
The submitted values will just end up right there in items.

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