Understanding navigation in JSF - jsf-2

Trying to build a simple JSF application. One i don't get is, what mechanism is to use to trigger page reload. I have tried following
<h:selectOneMenu
id="ChallengesListBox"
onchange="submit()"
valueChangeListener="#{bean.projectselected}">
<f:selectItems value="#{bean.projectnames}"/>
</h:selectOneMenu>
<h:commandButton value="submit" action="#{bean.submit}" />
with
public String submit() {
this.description.setRendered(true);
return null;
}
But this has no effect. The bean method
public String submit()
remains untouched, as I can see in debug mode.

This is not related to navigation. There are many causes why a bean action method is not invoked. You can find them all in this answer: commandButton/commandLink/ajax action/listener method not invoked or input value not updated
I suspest that you've either simply no <h:form>, or that you have multiple buttons in the form (the first one would then be invoked on submit()), or that the button is by itself not rendered during processing of the form submit.
Unrelated to the concrete problem, this JSF 1.x style approach is very clumsy. As you're apparently already on JSF 2.x, I suggest the following much simpler approach:
<h:selectOneMenu value="#{bean.projectname}">
<f:selectItems value="#{bean.projectnames}" />
<f:ajax render="somepanel" />
</h:selectOneMenu>
<h:panelGroup id="somepanel">
<h:outputText value="#{bean.description}" rendered="#{not empty bean.projectname}" />
</h:panelGroup>
(this will render the #{bean.description} value whenever the #{bean.projectname} is not null/empty according to the selection of the drop down list)
And make sure that you remove all binding attributes to the backing bean. Also make sure that the bean is #ViewScoped whenever you have input/button components inside the <h:panelGroup id="somepanel">.

Related

Why tree ajax events in primefaces don't work when bean scope is request?

My xhtml code is:
<p:tree id="attachTree" style="width: 100%;" value="#{detailsTaskBacking.attachRootNode}" selectionMode="single" selection="#{detailsTaskBacking.selectedNode}" var="node">
<p:ajax event="select" async="false" update=":roteiroAttachTab:formAttachForm:mediaPdf" listener="#{detailsTaskBacking.onNodeSelect}"/>
<p:treeNode expandedIcon="ui-icon-folder-open" collapsedIcon="ui-icon-folder-collapsed">
<h:outputText value="#{text['tasksbacking.tabAttach']}"/>
</p:treeNode>
<p:treeNode type="file" expandedIcon="ui-icon-document" collapsedIcon="ui-icon-document">
<h:outputText value="#{node.name}"/>
</p:treeNode>
</p:tree>
And my bean code is:
#request
...
public void onNodeSelect(NodeSelectEvent event) {...}
When run the project in debug mode selectedNode for argument event is null, why?
Why in primefaces tree ajax events not work when bean scope is request? I tested this with one bean in view scope and the selectedNode is not null, why?
That will happen if the model behind #{detailsTaskBacking.attachRootNode} incompatibly changes during postback. E.g. when it's reinitialized to null. You need to make sure that the model is exactly the same across postbacks on the same view. In case of a request scoped bean, you'd need to make sure that you prepare exactly the same model in #PostConstruct as it was when the form is being displayed. Another way is to just make the bean #ViewScoped so that the same bean instance lives as long as you postback on the same view.
See also:
How to choose the right bean scope?
commandButton/commandLink/ajax action/listener method not invoked or input value not updated - point 4

How to pass a variable on p:commandButton ajax request

I have a problem in handling a query string variable. I have a variable edit, that I append in the query string. By default it's true, meaning my page would be in edit mode, if false then the page would be in view mode. So in the page I read and assign the value of the edit query string variable to my backing bean:
#Named
#RequestScoped
public class UserAction {
private boolean edit;
//setter, getter
}
<ui:define name="metadata">
<f:metadata>
<f:viewParam name="edit" value="#{userAction.edit}" />
</f:metadata>
</ui:define>
Which works fine on first load of the page. For example edit=true, my page renders all the input components, but when I hit the clear button:
<p:commandButton value="Reset" process="#this" update="#form" action="#{userAction.clear()}">
<f:actionListener
type="org.omnifaces.eventlistener.ResetInputAjaxActionListener" />
<f:param name="edit" value="true"></f:param>
</p:commandButton>
The form re-renders without the input components because edit parameter is now false.
I tried, replacing RequestScoped with ViewScoped, but it seems that f:viewParam is not working for some reason.
I also tried setPropertyActionListener, the edit setter is called but when the getter is called the value reverts back to false.
I know that it is a scope problem because I don't encounter the same error with almost the same code but with ConversationScoped. But I just need this backing bean to be RequestScope.
Any idea?

How to hide components by selecting a new value on h:selectOneMenu?

I have a page with a h:selectOneMenu, and I want to hide a dataTable when I choose a new value on the h:selectOneMenu while some bean attribute values update. I'm trying diferent things, and I'm able to hide the dataTable by reloading the page. I have tried this using some JavaScript code, on onsomething attributes. In that case, those bean attribute values disapear although I use t:saveState (and I also need the view scope for the bean).
Here is a little example to clarify this:
<h:selectOneMenu id="list" value="#{Bean.id}">
<f:selectItems value="#{Bean.List}" var="element" itemLabel="#{element.name}" itemValue="#{element.id}"/>
<t:saveState value="#{Bean.id}"/>
<f:ajax listener="#{Bean.populateBean}" render=":form:period" event="change"/>
</h:selectOneMenu>
<h:selectOneMenu id="period" value="#{Bean.period}">
<f:selectItems value="#{Bean.listaPeriod}" var="period" itemLabel="#{period[1]}" itemValue="#{period[0]}"/>
<t:saveState value="#{Bean.period}"/>
</h:selectOneMenu>
<h:commandButton id="search" action="#{Bean.doSearch}"></h:commandButton>
<t:dataTable id="data" value="#{Bean.configList}" rendered="#{Bean.search}"
<t:column>
...
</t:dataTable>
And Bean.doSearch changes Bean.search to true. How can I hide the dataTable when I choose a new value on h:selectOneMenu id="list"?
EDIT:
In short, the search button renders the table, and I would want to hide that table when I just choose a new value on the "list" dropdown without reloading the page. Now, the <f:ajax> is used only to rerender the "period" dropdown value.
Thanks in advance!
Your question is hardly understandable, but if you want to kick the datatable out of your view on ajax request triggered by your dropdown, you need to enclose it in a component that's always present in the view so that HSF would know what to rerender when ajax call successfully finishes:
<h:panelGroup id="rerender">
<t:dataTable rendered="#{bean.condition}" ...>
....
</t:dataTable>
<h:panelGroup>
Of course, to get it working you should specify id of the component to be rerendered:
<h:selectOneMenu ...>
...
<f:ajax listener="#{bean.populate}" render="rerender" />
</h:selectOneMenu>
Note that if both dropdown and datatable components belong to the same form, it's not necessary to specify absolute id of the latter's parent. Also note that specifying event is redundant, as it already defaults to the right one. Finally, as you're on JSF 2.x, using save state is not necessary, just bind the values of your form data to a view scoped bean.
The last thing to note is the fact that you fail to conform to the Java Naming Conventions, the thing you should correct as soon as possible.

primefaces p:commandLink in p:datatable doesn't work [duplicate]

This is the code:
<h:form id="articleForm" >
<p:commandButton value="Select tags" ajax="true" >
<f:ajax execute="#form" render="#form :articleForm:tags" />
</p:commandButton>
<p:pickList id="tags" value="#{articleController.dualListModelForTags}" var="tag" itemLabel="#{tag.tag}" itemValue="#{tag}" converter="distinctTagConverter">
<f:facet name="sourceCaption">Distinct tags</f:facet>
<f:facet name="targetCaption">Connected tags</f:facet>
</p:pickList>
</h:form>
When the commandbutton is clicked, the getDualListModelForTags() in the backing bean is called and executed. In getDualListModelForTags() I make some modifications so I want the picklist to be updated. But the picklist(id=tags) is not rendered again. Only when I refresh the page, are the modifications made to the picklist.
The PrimeFaces <p:commandButton> component doesn't work together with <f:ajax>. You need to use the button's own ajax-targeted attributes instead. Instead of the <f:ajax execute> you should use <p:commandButton process>. But this already defaults to #form, so you can omit it. Instead of the <f:ajax render> you should use <p:commandButton update>. Specifying client IDs which are already covered by #form is unnecessary, so just #form is sufficient. Also the ajax="true" attribute is unnecessary as that's the default already.
So just this should do:
<p:commandButton value="Select tags" update="#form" />
Unrelated to the concrete problem, you're doing the business job inside a getter method. This is a bad idea. Do it in the button's action method instead. You also seem to be using a session scoped bean for view scoped data. This is a bad idea. Put the bean in the view scope instead.

Dynamically passing bean to rich:popupPanel

I have a base class, which is normal Java class. Three subclasses extend it which are #ViewScoped beans. There's a facelet using a dynamic variable. I have three xhtml pages which use this facelets with the three beans viz. bean1, bean2 and bean3 which are dynamically included in a rich:tab component on a main page.
So far so good. But on every page there are a few popups which should refer to the current bean. And since those popups need form tag inside them, I have included them outside the main page's form tags in order to avoid nested form tags. Now I want the popup to refer to current bean (bean1, bean2 or bean3, depending upon from where the popup is called) in question. How do I achieve this?
Try something like this:
Add a new bean (popupBean) that will contain reference to current bean in popup.
Add an action that will set needed bean as property of popupBean. Example:
<h:commandLink>
<a4j:ajax render="myPopup"/>
<f:setPropertyActionListener target="#{popupBean.currentBean}" value="#{bean1}"/>
<h:outputText value="Click ME!"/>
</h:commandLink>
Use show attribute of rich:popupPanel to show the popup:
<rich:popupPanel id="myPopup" modal="true" width="600" moveable="true"
show="#{not empty popupBean.currentBean}" onmaskclick="#{rich:component('myPopup')}.hide();" autosized="true">
<f:facet name="header"><h:outputText value="Cool popup!"/></f:facet>
<h:panelGrid style="margin: 0">
<h:panelGroup style="max-height: 400px;overflow-y: auto;" layout="block">
<h:outputText value="#{popupBean.currentBean.myBeanProperty}"/>
</h:panelGroup>
<h:button value="Close" onclick="#{rich:component('myPopup')}.hide();return false;"/>
</h:panelGrid>
</rich:popupPanel>

Resources