Here is the situation:
I have a component, whose value is a property of my ViewScoped bean, which gets a FacesMessage generated for it do to some error when the form is first submitted
On a subsequent user action, a h:commandlink is clicked, which uses f:ajax, and its actionlistener sets the component to no longer be rendered
Upon receiving the reponse, the component is no longer rendered (as expected), but the FacesMessage for it still remains and is displayed
I am using Mojarra JSF 2.1, and IceFaces 3.0 - although this example and the problematic behavior are seen using only standard JSF components. Here is a small example that demonstrates the behavior:
test.xhtml
<h:form id="testform">
<h:message for="tv"/>
<h:inputText id="tv" value="#{testBean.testVal}" rendered="#{testBean.testValRendered}" required="true" />
<h:commandButton value="Submit"/>
<h:commandLink actionListener="#{testBean.toggleTestVal}" value="Toggle input">
<f:ajax execute="#this" render="#form"/>
</h:commandLink>
</h:form>
Bean code
#ViewScoped
#ManagedBean(name = "testBean")
public class TestBean {
private String testVal;
private boolean testValRendered;
public TestBean() {
testValRendered = true;
}
public String getTestVal() {
return testVal;
}
public void setTestVal(String testVal) {
this.testVal = testVal;
}
public boolean isTestValRendered() {
return testValRendered;
}
public void setTestValRendered(boolean testValRendered) {
this.testValRendered = testValRendered;
}
public void toggleTestVal(ActionEvent ae) {
testValRendered = !testValRendered;
}
}
If I change the h:commandLink so that it does not use f:ajax, and set immediate='true' on it instead, then the message is removed properly. While this may work in some cases, I would like to understand why using f:ajax to render things as I have in my example does not work. Thanks.
The input component is submitted, processed and validated before its rendering condition has been toggled. The <h:message> isn't aware that the associated input component is not rendered. You'd like to check the very same rendering condition on the <h:message> as well:
<h:message for="tv" rendered="#{testBean.testValRendered}" />
<h:inputText id="tv" ... rendered="#{testBean.testValRendered}" />
Related
I'm testing the component "SelectOneMenu" on a jsf page. I'm populating this component dinamically though my ManageBean (that will get all Animals from database).
I would like to know if is possible to see the user selected item of that "SelectOneMenu" (combobox), I'm trying with value="#{animalsManage.animalSelect}" but it is only called on the beginning of the page. Also, I'm using an inputText to see the value of the selected intem of the "SelectOneMenu".
What I'm doing wrong?
JSF:
<body>
<ui:component>
<h:form>
<h:outputText value="Select one Mets File" />
<h:selectOneMenu id="combo" value="#{animalsManage.animalSelected}">
<f:selectItem itemLabel="Select..." noSelectionOption="true"/>
<f:selectItems value="#{animalsManage.allAnimals}" />
</h:selectOneMenu>
<h:inputText id="textbox" value="#{animalsManage.animalSelected }" />
</h:form>
</ui:component>
</body>
ManageBean:
#ManagedBean
#ViewScoped
public class AnimalsManage implements Serializable {
#EJB
private AnimalsFacadeREST animalsFacadeREST;
private String animalSelected;
private List< SelectItem> selectAnimals;
public List<SelectItem> getAllAnimals() {
List<Animals> al = animalsFacadeREST.findAll();
selectAnimals = new ArrayList< SelectItem>();
int i = 0;
for (Animals animal: al) {
selectAnimals.add(new SelectItem(i, animal.getName()));
i++;
}
return selectAnimals;
}
public String getAnimalSelected() {
return animalSelected;
}
public void setAnimalSelected(String animalSelected) {
this.animalSelected = animalSelected;
}
}
There are many solutions to the presented problem. I present here two basic ideas.
Server-side solution. Simply attach <f:ajax> tag inside your <h:selectOneMenu> to update selected values and rerender user's choice, like in
<h:selectOneMenu id="combo" value="#{animalsManage.animalSelected}">
<f:selectItem itemLabel="Select..." noSelectionOption="true"/>
<f:selectItems value="#{animalsManage.allAnimals}" />
<f:ajax execute="combo" render="textbox" />
</h:selectOneMenu>
<h:inputText id="textbox" value="#{animalsManage.animalSelected }" />
If you like, you may also do some custom logic with selected element in ajax listener by specifying listener="#{animalsManage.performCustomAjaxLogic}" of <f:ajax> tag.
Client-side solution. Simply update element with id="textbox" on basic change event. So, if you use jQuery the solution will be
$('#combo').change(function() {
$('#textbox').val($('#combo').val());
});
Thought the client-side solution will bind only text value of your input component.
I am running JBoss 7.1.0.Final with the default JSF 2.1 .
I have been having problems getting the render attribute of a f:ajax to work
Here is my code
<h:form>
<h:panelGrid>
<h:inputText value="#{bean.text}" >
<f:ajax event="keyup" render="text"/>
</h:inputText>
<h:outputText id="text" value="#{bean.text}" />
</h:panelGrid>
</h:form>
With a bean:
#ManagedBean(name = "bean")
public class Bean
{
private String text;
public String getText()
{
return text;
}
public void setText(String text)
{
this.text = text;
}
}
The page renders but the value entered in the inputtext does not render as outputtext.
There does seem to be some interaction with the server as I get
JBAS010152: APPLICATION ERROR: transaction still active in request with status 0
happening on each keyup event?
Note that I am running this within Seam 2.3
I was playing around with primefaces components, when I stumbled upon this issue...
I have a sample page which contains the following,
<h:form>
<p:panel id="p1">
<p:commandButton value="display" actionListener="#{myTestBean.display}" update="p2"> </p:commandButton>
</p:panel>
<p:panel id="p2" rendered="#{myTestBean.show}">
<p:inputText value="#{myTestBean.val1}" id="t1"></p:inputText>
<p:inputText value="#{myTestBean.val2}" id="t2"></p:inputText>
<p:commandButton value="click me" update="#form" action="#{myTestBean.disply}"></p:commandButton>
</p:panel>
</h:form>
My backing bean contains the following,
public class Testbean implements Serializable {
private String val1;
private String val2;
private boolean show;
//getters and setters for the above...
public void display(){
if(show == false){
setShow(true);
}
}
public void disply(){
System.out.println("I am here");
val1 = "hi";
val2 = "hello";
if(show == false){
setShow(true);
}
}
}
Now, the catch here is, when I click my first button(display) the below panel(p2) gets rendered correctly. But when I click on the second button(click me) the panel gets hidden and also on click of second button it never goes to the backing bean method 'disply()'.
I have used action listener in the second button but again the same behavior. Also, I have given the update = "p2" in the second button, even that didn't yield what I wanted.
Could anyone help me out with this and let me know where and what I am doing wrong?
Thank you.
The bean needs to be placed in the view scope in order to remember all previous (ajax) actions on the same view.
#ManagedBean
#ViewScoped
public class TestBean {
// ...
}
When the bean is placed in the request scope, then the boolean show would be reinitialized to default false and thus the rendered attribute would evaluate false while JSF is looking for the action method to be invoked and hence the action method would be never found and invoked.
See also:
How to choose the right bean scope?
commandButton/commandLink/ajax action/listener method not invoked or input value not updated
When using actionListener="#{myTestBean.display}", the backinbean method should be
public void display(**ActionEvent event**){
if(show == false){
setShow(true);
}
}
and an ActionEvent parameter must be declared.
I surrounded the button as shown below
<h:form>
<h:commandButton styleClass="toggle_btn" action="#{buttonNavBean.show()}" style=" font-family: sans-serif; color: black;" value="Sign In/Sign Up"></h:commandButton>
</h:form>
I faced the same challenge too. I tried to search online but all in vain. But after several trials, I came to figure out that since I was using the commandButton to set the value of the rendered panel, it was not possible to work out of UIForm, Therefore, I surrounded the commandButton with UIForm and it worked correctly as I wanted.
I have been looking for this for a while and haven't found it. It is surprisingly complicated as shown in this old IceFaces tutorial.
What is needed is a UIInput component that will set a java.util.TimeZone property, allowing the user to select it from a map or a list on the screen. Before I dive in to write one for myself -- does anyone know of an available component that does this?
Use <h:selectOneMenu> to represent a dropdown list. Use <f:selectItems> to feed it with a E[], List<E>, SelectItem[] or List<SelectItem> as value.
Here's how it can look like at its simplest:
#ManagedBean
#ViewScoped
public class Bean implements Serializable {
private String timeZoneID; // +getter +setter
private String[] timeZoneIDs; // +getter only
#PostConstruct
public void init() {
timeZoneIDs = TimeZone.getAvailableIDs();
// You may want to store it in an application scoped bean instead.
}
public void submit() {
System.out.println("Selected time zone: " + TimeZone.getTimeZone(timeZoneID));
}
// ...
}
with this view:
<h:form>
<h:selectOneMenu value="#{bean.timeZoneID}" required="true">
<f:selectItem itemValue="#{null}" itemLabel="Select timezone..." />
<f:selectItems value="#{bean.timeZoneIDs}" />
</h:selectOneMenu>
<h:commandButton value="submit" action="#{bean.submit}" />
<h:messages/>
</h:form>
If you want to make it a fullworthy TimeZone property, you'd need to bring in a #FacesConverter(forClass=TimeZone.class) which should be pretty straightforward enough.
I already created the bean, and it gets the value from the textbox, my problem is how can i pass it to another java class?
Just pass it as method argument the usual Java way. You can do it in the action method.
E.g.
<h:form>
<h:inputText value="#{bean.input}" />
<h:commandButton value="Submit" action="#{bean.submit}" />
</h:form>
with
private String input; // +getter +setter
public void submit() {
YourAnotherClass yourAnotherClass = new YourAnotherClass();
yourAnotherClass.process(input);
}