PanelGroup is not getting rendered after clicking the command button action - jsf-2

I have a 2 set of panel groups . one panel group contains a fieldset and inside, two radio buttons and one command button .Based on the selection of radio button, respected value will be displayed in another panel group through ajax call. But issue is after the radio button selection when the command button is clicked the other panel group is not at all rendered when the first time page loads . when i refresh everything works fine. I could not able to figure out why the renderedPanelGroup value is not set to true even that is being set in the command action .Here is my code.
test.xhtml
<h:form id="parentformid">
<h:panelGroup id="demandDashBoardPanelGroupID">
<fieldset>
<legend>Demand Dashboard</legend>
<table>
<tr>
<td>
<h:selectOneRadio id="groupbyid" value="#{demandManagedBean.selectedRadioButton}" >
<f:selectItem itemLabel="Group By Creation Date Time" itemValue="1" />
<f:selectItem itemLabel="Group By Location" itemValue="2" />
</h:selectOneRadio>
</td>
<td>
<h:commandButton id="fetchbuttonID" value="Fetch"
action="#{demandManagedBean.displayDemandRequestsTable}">
<f:ajax render=":parentformid:demandrequestpanelgrpid"execute="#form" />
</h:commandButton>
</td>
</tr>
</table>
</fieldset>
</h:panelGroup>
//For checking demandManagedBean.renderedPanelGroup value. it is giving always false.Thats why panel group is not getting rendered.
<h:outputText value="#{demandManagedBean.renderedPanelGroup}" />
<h:panelGroup id="demandrequestpanelgrpid" rendered="#{demandManagedBean.renderedPanelGroup}">
<fieldset id="demandrequestfieldsetid">
<legend >Demand Requests</legend>
<h:outputText rendered="#{demandManagedBean.renderFirstTable}" value="first table"/>
<h:outputText rendered="#{demandManagedBean.renderSecondTable}" value="second table"/>
</fieldset>
</h:panelGroup>
//Backing bean cmd action
private String selectedRadioButton ="1";
private boolean renderFirstTable ;
private boolean renderSecondTable;
private boolean renderedPanelGroup ;
//getter and setter methods
public void displayDemandRequestsTable(){
if(selectedRadioButton!= null && selectedRadioButton.endsWith("1")){
renderFirstTable = true;
renderSecondTable= false;
}else if(selectedRadioButton!= null && selectedRadioButton.endsWith("2")){
renderFirstTable = false;
renderSecondTable= true;
}
renderedPanelGroup = true;
}

You cannot update elements which are not rendered , rendered=false "is a JSF way to" to remove elements from the DOM Tree ,
its not like css display:none or visibility:hidden <- this two will keep the elements in the DOM tree but hidden , while the JSF rendered=false wont even render (keep) the element in the DOM tree (you wont even see it in the "view source" of the page)
So in you case you need to wrap the panelGroup with another `panelGroup' and update the id of the wrapper
<h:panelGroup id="demandrequestpanelgrpid">
<h:panelGroup rendered="#{demandManagedBean.renderedPanelGroup}">
.
.
.
also look at similar question
Can you update an h:outputLabel from a p:ajax listener?

Related

Get sibling element from PrimeFaces datatable row

I have a datatable created in PrimeFaces which receives and render a list of objects. At the end of the row I have a commandButton element and when it is used it do some stuff on the managedBean on the server.
All the data about the current row is retrieved using an object id placed in the command button in the param attribute.
The problem is that I have a selectOneMenu element and it is not related to the object. I select one value that affects the logic behind.
Here is the table:
<h:panelGrid id="panel" columns="2" bgcolor="#cce4ff"
cellpadding="10" cellspacing="1" rendered="#{indexBean.showChannelList}"
style="margin-top: 10px; margin-left: 100px;">
<p:dataTable var="program" value="#{indexBean.programList}" style="width:1000px;"
paginator="True" rows="10" rowIndexVar="row" sortBy="#{program.id}"
paginatorPosition="bottom" widgetVar="programDT" id="programDT">
... That the select
<p:column headerText="text" width="15%">
<h:selectOneMenu id="select-valability" value="#{indexBean.valabilitySelected}" disabled="#{indexBean.disabled}" style="font-size: small;">
<f:selectItems value="#{indexBean.listValabilities}" />
<f:param value="#{program.id}" />
<f:ajax resetValues="true" />
</h:selectOneMenu>
</p:column>
... and there is the command button
<p:column headerText="text" width="20%" style="text-align: center;">
<h:commandButton id="cmd-button-id" value="gen JSON" action="#{indexBean.action}"
style="width: 200px; height: 30px;"
class="ui-button ui-widget ui-state-default ui-corner-all"
>
<f:param name="programId" value="#{program.id}" />
</h:commandButton>
</p:column>
I want to be able to get the value of the select element from that specific row from which the action was triggered.
I've try with context.findComponent() but it gives me null even if I put the absolute path to the element with the index generated by JSF table as form:table:index:staticIdOfSelect.
I don't know how to get the sibling element. That was another though.
From the bean class:
#ManagedBean
#SessionScoped
public class IndexBean
I'm really stuck here.
Thanks in advance!
Use some element on the row to set an ajax listener in the bean to store the data and then update="the element" you want to get the information from.

jsf changing class of an element

I want to change a div's class dynamically based on if an input value is true or false. Thought the function that validates the input is called the class is never changed. Here's the xhmtl:
<td>
<div class="#{regBean.nameclass}">
<h:inputText class="form-control input-sm" value="#{regBean.name}">
<f:ajax event="blur" listener="#{regBean.validateName}" render="namemsg" />
</h:inputText>
</div>
</td>
<td class="error">
<h:outputText class="error-msg" id="namemsg" value="#{regBean.nameMsg}"></h:outputText>
</td>
and here's the function from the according bean:
private static final String SUCCESS="form-group has-success";
private static final String ERROR="form-group has-error";
public void validateName(){
if(ValidatorUtilities.empty(name)){
nameMsg="Παρακαλώ εισάγετε όνομα!";
}
nameMsg=ValidatorUtilities.validateName(name);
if(nameMsg.equals("")){
nameclass=SUCCESS;
validations.put("name",true);
}
else{
nameclass=ERROR;
validations.put("name",false);
}
}
thought the message at element with id="namemsg" is correctly shown the class remains the same. Is there anything wrong or am I going for the wrong implementation and should do this client side by jquery?
Note:I've set the getter-setter for the string nameclass
Your code is not re-rendering the <div>. Your code is only re-rendering the <h:outputText>. I'm not sure why and how exactly you expected that the <div> is also covered by the re-rendering. All you need to so is to specify its client ID in the render attribute as well. You only need to replace <div> by <h:panelGroup layout="block">, because rendering can only target true JSF components.
<td>
<h:panelGroup id="field" layout="block" styleClass="#{regBean.nameclass}">
<h:inputText ...>
<f:ajax ... render="field namemsg" />
</h:inputText>
</h:panelGroup>
</td>
<td class="error">
<h:outputText id="namemsg" ... />
</td>
Unrelated to the concrete problem, your whole validation approach is utterly broken. You're supposed to use a true Validator and a <h:message>, exactly like as shown in every decent JSF book. This is also a strong hint that you still don't have one. I warmly recommend to work on that first.
See also:
How to create JSF form with AJAX data validation
How to perform validation in JSF, how to create a custom validator in JSF

Primefaces component not refreshing

I have been looking at Primefaces 3.4.2 since IceFaces 3.2.0 has too many issues. I have a dataGrid of vehicles which are contained in a panel. I have an add button and each vehicle panel contains a remove button.
The add works fine; it adds a new vehicle panel each time. The issue is when I delete a vehicle, the panel is removed, but the value(s) remain. For instance, if I have 3 vehicles with the year as 2008, 2010, 2012, and then I delete the first vehicle, you'd think you would see 2 panels remaining with the year as 2010, and 2012. Instead, I see 2008 and 2012. The backing bean is doing it correctly and I do see the correct values if I manually refresh the screen. Now that I have presented my case here's the code:
<p:dataGrid id="vehicleGrid" var="currentVehicle" value="#{vehicleInfoBean.getVehicleList()}" columns="#{vehicleInfoBean.getVehicleList().size()}" styleClass="vehicleInfoPanel" rowIndexVar="rowIdx">
<p:panel header="VEHICLE ##{rowIdx+1}:" style="width:100%" styleClass="textEntryInputTable">
<h:panelGrid columns="1" style="width:100%" styleClass="vehicleInfoPanel">
<ui:include src="../components/vehicleinfo/vehiclecomponents.xhtml">
<ui:param name="currentVehicle" value="#{currentVehicle}" />
<ui:param name="labelOnly" value="false" />
</ui:include>
<div class="deleteButton">
<p:commandButton value="Remove" label="Delete Vehicle" action="#{vehicleInfoBean.deleteVehicle}" update=":vehicleInfoForm:vehicleGrid" process="#this">
<f:setPropertyActionListener value="#{currentVehicle}" target="#{vehicleInfoBean.currentVehicle}" />
</p:commandButton>
</div>
</h:panelGrid>
</p:panel>
</p:dataGrid>
Any ideas? I have tried all sorts of update values including #form, but it's all the same. I haven't used a dataGrid before but I need the iterative capabilities that ice:panelSeries has.
UPDATE: Here's the code in the include:
<h:panelGrid columns="2">
<p:inputText id="vinInput" styleClass="stdFieldControl" value="#{currentVehicle.vin}" label=""
required="true" requiredMessage="VIN is required" >
<p:ajax update="#this vinMsg"/>
</p:inputText>
<p:message id="vinMsg" for="vinInput" errorClass="ui-state-error-text"/>
<p:outputLabel value="-----OR-----"/>
</h:panelGrid>
1/14/2013 - Updated code
<p:dataGrid id="vehicleGrid" var="currentVehicle" value="#{vehicleInfoBean.getVehicleList()}" columns="#{vehicleInfoBean.getVehicleList().size()}" styleClass="vehicleInfoPanel" rowIndexVar="rowIdx">
<p:panel header="VEHICLE ##{rowIdx+1}:" style="width:100%" styleClass="textEntryInputTable">
<h:panelGrid columns="1" style="width:100%" styleClass="vehicleInfoPanel">
<p:inputText id="vinInput" styleClass="stdFieldControl" value="#{currentVehicle.vin}" label="" required="#{empty param['vehicleGrid:0:btnDelete'] and empty param['btnAdd']}" requiredMessage="VIN is required" >
</p:inputText>
<p:message id="vinMsg" for="vinInput" errorClass="ui-state-error-text"/>
<p:outputLabel value="-----OR-----"/>
<h:inputText id="yearInput" styleClass="stdFieldControl" value="#{currentVehicle.year}" label=""
required="#{empty param['vehicleGrid:0:btnDelete']}" requiredMessage="Year is required">
</h:inputText>
<p:message id="yearMsg" for="yearInput"
errorClass="ui-state-error-text"/>
<div class="deleteButton">
<p:commandButton id="btnDelete" value="Remove" label="Delete Vehicle" action="#{vehicleInfoBean.deleteVehicle}" update="#form">
<f:setPropertyActionListener value="#{currentVehicle}" target="#{vehicleInfoBean.currentVehicle}" />
</p:commandButton>
</div>
</h:panelGrid>
</p:panel>
</p:dataGrid>
The add code looks like this:
<div class="addButton" style="padding-left: 2.17%; float: left; clear: both">
<p:commandButton id="btnAdd" value="AddVehicle" label="Add Vehicle" actionListener="#{vehicleInfoBean.addVehicle}" update="vehicleGrid"/>
</div>
Instead of putting the check on the buttons, I decided to set the required attribute of the components referring to the buttons. This code works if I hardcode the iterator index. For example, required="#{empty param['vehicleGrid:0:btnDelete']}". This code points to the first delete button in the panelGrid. What I need is to dynamically derive the index to this - required="#{empty param['vehicleGrid:#{rowIdx}:btnDelete']}". The add button was easy since it doesn't reside in an iterator. How do I code the param in a way that I can dynically refer to the rowId of the panelGrid? The RowId looks confusing but this is coded in a way that each Vehicle Panel is displayed next to the previous panel. The row in this case can be thought of as a column. Anyone have any ideas?

Empty string in Bean not overwriting previous value in h:inputText

JSF 2 problem. I have a hidden edit area on my form. When the user clicks the Edit button, I set a bean property to true to display the area (this is a bit of a simplification) and set another bean property to the value being edited. This variable is referred to like:
<h:inputText value="#{bean.stringValue}" />
When the user cancels out of editing, I hide the edit area.
Let's say the user then wants to edit another item, but this one's value is the empty string (""). Using the same code, stringValue is set to the emptyString and the area displays.
However, the value from the previous edit is displayed, not an empty text box.
Without resorting to JavaScript, is there a way to make this work?
Edit: Following is as close as I can come to a SSCCE. As you see, I am activating in-place editing inside a table. I'm also using ICEfaces, but nothing special in this case.
<table>
<tbody>
<ui:repeat var="cfi"
value="#{evDetailBean.completeEvent.listCompleteCashFlowItems}">
<ice:panelGroup rendered="#{!cfi.editThisOne}">
<tr>
<td>#{cfi.cfiName}</td>
<td>#{cfi.absOfAmount}</td>
<td>#{cfi.frequencyDescr}</td>
<td>#{cfi.cfiToFrom}</td>
<td>#{cfi.assetPoolName}</td>
<td style="text-align: center"><h:commandLink
actionListener="#{cfi.editCfiListener}" value="Edit" />    <h:commandLink
value="Delete" actionListener="#{cfi.deleteCfiListener}" />
</td>
</tr>
</ice:panelGroup>
<ice:panelGroup rendered="#{cfi.editThisOne}">
<tr>
<td><ice:inputText value="#{evDetailBean.newCFIName}"
style="width:118px;" partialSubmit="true" immediate="true" validator="#{evDetailBean.valNewCFIName}" /></td>
<td>xxx</td>
<td>xxx</td>
<td>xxx</td>
<td>xxx</td>
<td style="text-align: center;"><ice:commandButton
value="Save" immediate="true"
actionListener="#{evDetailBean.saveEditCfiListener}"
styleClass="plumvo-button"
style="float:left; vertical-align: middle;" />   
<ice:commandLink value="Cancel" style="vertical-align: middle;"
actionListener="#{cfi.cancelEditCfiListener}" /></td>
</tr>
</ice:panelGroup>
</ui:repeat>
</tbody>
And this is the actionListener (in part):
public void editCfiListener(ActionEvent e) {
EvDetailBean evDetailBean = completeEvent.getEvDetailBean();
evDetailBean.setNewCFIName(this.getCfiName());
// initialize more fields
editThisOne = true; // This causes the row being edited to open up with modifiable fields.
}
Thanks in advance for your help.
Just check in your bean after submit if stringValue is "" and if so, set it to null and visible property to false.
the action , the bean function you are calling on click of edit button. inside that clear the stringValue variable.

primefaces autocomplete when cleared field giving previuos results of page on clicking submit button

I am using an autocomplete tag of prime faces which retrieves results from a database.
The problem is that when I submit the form leaving the autocomplete field empty the results I get on the page are those of the previous request (the previously selected autocomplete value) - it only gets cleared when I refresh the page.
I want that on each submit, without refreshing the browser page, if i clear out the value in the field using backspaces and submit the form it should give the correct result for this particular instance, not previous one.
I am also using some textfields in the jsf page form but those don't have this problem.
Can anyone offer guidance as to how this problem can be corrected?
EDITED:
Code:
<h:form>
<h:dataTable id="Ressult" value="#{input.searchResults}" var="r">
<h:column>#{r.ID}</h:column>
<h:column>#{r.Name}</h:column>
</h:dataTable>
<tr>
<td>Current Education Level</td>
<td>
<h:panelGrid styleClass="text-box">
<p:autoComplete id="education" value="#{input.education}"
completeMethod="#{input.getautocomplete}" var="a"
itemLabel="#{a.Name}" itemValue="#{a}"
converter="edConverter" forceSelection="true" />
<p:column>#{a.Name} - #{a.id}</p:column>
</h:panelGrid>
</td>
</tr>
<tr>
<td>City</td>
<td>
<h:selectOneMenu id="txtCity" styleClass="select-field"
value="#{input.cityId}">
<f:selectItem itemLabel=" Please Select" itemValue="0">
</f:selectItem>
<f:selectItems value="#{input.cities}"></f:selectItems>
</h:selectOneMenu>
</td>
</tr>
<tr>
<td>Name of Person</td>
<td>
<h:inputText id="txtName" value="#{input.nameOfPerson}"
styleClass="text-box"></h:inputText>
</td>
</tr>
<h:commandButton id="btnSearch" value="Search"
action="#{input.searching}">
<f:ajax execute="#form" render="Ressult"></f:ajax>
</h:commandButton>
</h:form>
And here is the bean code:
public class Input
{
private Education education;
private List<SelectItem> cities;
private Integer cityId;
private String nameOfPerson;
private List<Results> searchResults;
//getters and setters
public String searching()
{
searchResults=dao.getSearchResults(cityId,education,nameOfPerson);
return "success";
}
public void autocomplete(String query)
{
//AUTOCOMPLTE lIST CODE HERE
}
}
By update, if you mean new results to be shown when new items selected, then yes - the form should be updated but autocomplete somehow takes the previously selected value and shows results according to that. At least until I refresh the page - only then is autocomplete's previous is removed.
I had the same problem with my autocomplete widget.
When I removed its id attribute it worked. Maybe a bug in Primefaces.
You may have two things to do:
Prevent the user from submission by pressing the Enter key by doing the following in your form:
<h:form onkeypress="return event.keyCode != 13;">
Using itemSelect/itemUnselect features provided to empty the field in the Bean:
<p:ajax event="itemSelect"
listener="#{autoCompleteBean.handleSelect}" global="false"
update=":some:where" />
<p:ajax event="itemUnselect"
listener="#{autoCompleteBean.handleUnselect}" global="false"
update=":some:where" />
<!-- rest of your facelet stuff -->
In the Bean:
public void handleSelect(final SelectEvent event) {
final Search search = (Search) event.getObject();
// do your addition here
}
public void handleUnselect(final UnselectEvent event) {
final Search search = (Search) event.getObject();
// do your substraction here
}
Well if i understand your question correctly your list of auto completion is shown after the post. And you use your form to submit time after time to the same page.
Your bean looks a little bit odd. Because you're calling in the page the autocomplete method: getautocomplete but that one doesn't exists in your bean.
Use the autocomplete in this way:
<p:autoComplete id="education" value="#{input.education}" completeMethod="#{input.autocomplete}" var="a" itemLabel="#{a.Name}" itemValue="#{a}" converter="edConverter" forceSelection="true" />
And in your bean:
public List<Education> autocomplete(String query)
{
List<Education> educations = new ArrayList<Education>();
//search with query in your dao something like:
educations = dao.searchEducation(query);
return educations;
}
fixed on 5.2, upgrade your primefaces jar
here the log issue
https://code.google.com/p/primefaces/issues/detail?id=7592
To fix the subject issue you just remove the forceselection
or make it as false.
Just process event to server. Works with forceselection="true"
<p:ajax event="itemUnselect" global="false" />

Resources