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
Related
I'm using below composite component:
<composite:interface>
<composite:attribute name="inputId" />
</composite:interface>
<composite:implementation>
<h:panelGrid id="myTableId">
<h:inputText id="#{cc.attrs.inputId}" value="..." />
...
</h:panelGrid>
</composite:implementation>
And I'm using it in my form as below:
<h:form id="myForm">
<myCompositeComp:test inputId="myInputTextBoxId" />
<h:form>
I've verified the view source for the page and this is how it is generated:
<table id="myForm:j_idt90:myTableId">
...
<input type="text" id="myForm:j_idt90:myInputTextBoxId" />
</table>
How can I get rid of j_idt90 here? Is it the id of my composite component? I read from one of BalusC post that this issue will get fixed if I declare id as static. But I'm not able to identify the place to declare it in my code. Also can I assume <h:panelGrid> is a kind of UINamingContainer?
Yes it is the id of your composite component, <h:panelGrid> is not a UINaminContainer but the composite component is (it has to be, otherwise you would have duplicate IDs if you use it several times inside the same form for example).
Why do you need to get rid of the ID? You can set it yourself if that solves your problem:
<h:form id="myForm">
<myCompositeComp:test id="myComp" attr1="" attr2="" />
<h:form>
the genereated html should look like this:
<table id="myForm:myComp:myTableId">
....
<input type="text" id="myForm:myComp:myInputTextBoxId"
</table>
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.
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" />
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?
I'm upgrading from JSF 1.2 to JSF 2 and Richfaces 3.3 to 4.
I've tried various version of JSF2 (2.02, 2.06, etc) and all give the same error.
I'm getting the following error that has been hurting my head for hours now!
SEVERE: Error Rendering View[/my-testfile.xhtml]
javax.el.PropertyNotFoundException: /templates/components-navigation.xhtml #31,54 rendered="#{component.allowed}": Property 'allowed' not found on type org.richfaces.component.UIRepeat
/templates/components-navigation.xhtml
<a4j:outputPanel rendered="#{loginBean.loggedIn}">
<a4j:repeat var="menugroup" value="#{componentNavigator.groups}">
<a4j:region rendered="#{menugroup.itemCount > 0}">
<div class="panel_menu">
<table class="title" border="0" width="100%">
<tr>
<td>
<h:outputText class="text" value="#{messages[menugroup.id]}" />
</td>
</tr>
</table>
<table class="links" border="0" width="100%">
<tbody>
<a4j:repeat var="component" value="#{componentNavigator.components}">
<a4j:region rendered="#{component.allowed}">
<a4j:region rendered="#{component.groupId == menugroup.id}">
<tr class="#{component.current?'active':'unactive'}">
<td> </td>
<td class="text" width="100%">
<h:commandLink action="#{component.getCommandAction}" actionListener="#{componentNavigator.initControllerBean}">
<span style="display:block;">
#{messages[component.id]}
</span>
<f:attribute name="controllerBean" value="#{component.controllerBean}" />
<f:setPropertyActionListener target="#{componentNavigator.currentComponent}" value="#{component}" />
</h:commandLink>
</td>
</tr>
</a4j:region>
</a4j:region>
</a4j:repeat>
</tbody>
</table>
</div>
</a4j:region>
</a4j:repeat>
</a4j:outputPanel>
Line 31 is:
<a4j:region rendered="#{component.allowed}">
Any ideas why the property is not been found? Is there a know issue with the repeat component?
#{component} is a reserved and implicit EL object which refers to the current JSF component. It can be used as follows:
<h:inputText value="#{bean.value}" styleClass="#{component.valid ? 'ok' : 'error'}" />
In the above example, the #{component} resolves to an UIInput instance representing the current <h:inputText>, which in turn has a isValid() method. Upon submit, when the component has a validation error, the error style class will be set (which may have for example a reddish background color), else the ok style class will be set. It's like as this in JavaScript.
You should give your scoped variables a different name. Do not use the name of one of the following reserved EL objects in JSF:
#{component} - the current UIComponent
#{facesContext} - the current FacesContext
#{request} - the current HttpServletRequest
#{session} - the current HttpSession
#{application} - the ServletContext
#{cc} - the current composite component
#{param} - the current request parameter map
#{paramValues} - the current request parameter values map
#{requestScope} - the current request attribute map
#{viewScope} - the current view attribute map
#{sessionScope} - the current session attribute map
#{applicationScope} - the application attribute map
#{header} - the current request header map
#{cookie} - the current request cookie map
Your 'component' bean needs a
public boolean getAllowed() {
return this.allowed;
}
and
public void setAllowed(boolean allowed) {
this.allowed = allowed;
}
method. A property is a field in your bean, which needs a public getter and setter method. Most IDEs support generating those methods look out for something like "Source --> Generate Getter and Setter".
Another possibility would be to call a method directly. Something like,
<a4j:region rendered="#{component.isAllowed()}">
with a bean code
public boolean isAllowed() {
return this.allowed;
}
If you've already getter and setter in your componentNavigator bean it would be usefull if you could post it here (or parts of it).
Richard
I changed:
<a4j:repeat var="component" value="#{componentNavigator.components}">
to:
<a4j:repeat var="myComponent" value="#{componentNavigator.components}">
and it's all good now :)
I stumbled across this issue which gave me the clue:
https://issues.jboss.org/browse/RF-8026