Dynamically passing bean to rich:popupPanel - jsf-2

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>

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

#postconstruct method gets called during ajax-refresh the main content part by navigation menu

I am trying to ajax-refresh the main-content from navigation menu.
The requirement is exactly the same in the link
How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)
following the pattern answered by BalusC,
<h:panelGroup id="content" layout="block">
<h:form id="contentform">
<h:panelGroup rendered="#{bean.page == 'include1'}">
<ui:include src="include1.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{bean.page == 'include2'}">
<ui:include src="include2.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{bean.page == 'include3'}">
<ui:include src="include3.xhtml" />
</h:panelGroup>
</h:form>
Each xhtml has its own managed bean with #PostConstruct method, the problem is all the #PostConstruct method gets called irrespective of rendered condition.
<ui:include/> is a taghandler while <h:panelGroup/> is a render-time tag. The difference is that they're both active at different times during the lifecycle of the build. In this particular case, <ui:include/> is active and processed before the <h:panelGroup/>. So while your render condition might hide the dynamic include at render time, the include would still go thru the grinder anyway, resulting in the processed managed beans.
You should place the rendered attribute on the <ui:include/> instead. Be sure that the render condition is not also dependent on some other render time construct

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.

How to edit data in Primefaces DataTable without in-cell editing?

I have 2 pages.
Add Page for add a new item
List Page for show all items
When I click on Edit icon on List Page, I want to show selected data on Add Page for editing and update its data if I click on save button. How to do this?
Pass the row identifier as a parameter to the button. For example, assuming that #{item} is the currently iterated item and has some Long id property which uniquely identifies the item.
<p:button icon="ui-icon-pencil" outcome="edit.xhtml">
<f:param name="id" value="#{item.id}" />
</p:button>
In the target page, edit.xhtml, you can use <f:viewParam> to convert, validate and set it as a bean property.
<f:metadata>
<f:viewParam name="id" value="#{bean.item}" required="true" converter="itemConverter" />
</f:metadata>
...
<p:inputText value="#{bean.item.name}" />
<p:inputText value="#{bean.item.shortName}" />
See also:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
Communication in JSF 2.0 - Processing GET request parameters

Understanding navigation in JSF

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">.

Resources