PrimeFaces dialog lazy loading (dynamic="true") does not work? - jsf

I have recently changed all my beans from RequestScoped to ViewScoped. Suddenly, the lazy loading of dialogs does not work. I am using PrimeFaces JSF library.
<html>
<h:body>
<f:view>
<h:form>
<p:commandButton id="addId" value="Add" title="Add" type="button" onclick="dlgMultiFileSelect.show();"/>
...
</h:form>
<p:dialog header="Dialog" widgetVar="dlgMultiFileSelect" modal="true" resizable="true" dynamic="true">
<ui:include src="/dialogs/media_browser.xhtml"/>
</p:dialog>
</f:view>
</h:body>
</html>
Seems like dynamic="true" does not work since the backing bean in media_browser.xhtml gets initialized immediately, and not when button is clicked.
Am I doing something wrong?
Using PrimeFaces 3.5.0.

have found some pretty easy workaround:
Let's quote BalusC's answer on this other question:
Skip executing <ui:include> when parent UI component is not rendered
The <ui:include> runs as being a taghandler during the view build time, while the rendered attribute is evaluated during the view render time.
Regarding his first proposal:
Use a view build time tag like <c:if> around the <ui:include> part.
So first add some new method to your bean. (may even be useful in some application scoped bean for reuse)
public boolean isAjaxRequest() {
boolean val = FacesContext.getCurrentInstance().getPartialViewContext().isAjaxRequest();
return val;
}
Then enclose your <ui:include> inside following <c:if>:
<p:dialog id="yourDlg" header="Dialog" widgetVar="dlgMultiFileSelect" modal="true" resizable="true" dynamic="true">
<c:if test="#{applicationBean.ajaxRequest}">
<ui:include src="/dialogs/media_browser.xhtml"/>
</c:if>
</p:dialog>
So at page load time, the request isn't ajax... and on other ajax requests on base page, the dialog won't be updated...
But if you trigger your dialog
<p:commandButton id="addId" value="Add" title="Add" type="button"
oncomplete="dlgMultiFileSelect.show();" update=":yourDlg"/>
and update it's content, it will finally be rendered!
Please note following changes: The p:dialog id, p:commandButton update and p:commandButton oncomplete

Facelet tag ui:include will get processed earlier in the cycle and hence it is getting initialized. If you want to update the content of the dialog on button click, you need to do so using the update="id of the dialog" on your commandButton. You can use for your ui:include so that the page is not loaded initially.

Related

JSF rendered method is not invoked in the second time

I have next a4j:jsFunction
<a4j:jsFunction name="renderOnBusinessErrorEvent" execute="#none" bypassUpdates="true" immediate="true"
render="securityForm">
</a4j:jsFunction>
and JSF form with some dialog inside
<h:form id="securityForm">
<h:panelGroup rendered="#{someCondition}">
......
</h:panelGroup>
</h:form>
In my business logic it has to be executed twice consequently. In the first time all is fine. Rendered method is invoked and the expected dialog is present on the page. In the second time rendered method is not invoked, but model has been changed and I expect that dialog will not be present on the page. I supposed that it's some richfaces issue and I tried to use f:ajax
<a4j:jsFunction name="renderOnBusinessErrorEvent" execute="#none" bypassUpdates="true" immediate="true">
<f:ajax event="begin" render=":securityForm"/>
</a4j:jsFunction>
but unsuccessfully. Rendered method still not invoked in the second time. What is it? Some JSF optimization or bug? What's the workaround?
JSF version 2.1.19
The problem was in <h:panelGroup rendered="#{someOtherCondition}">
over h:form which equals false after the first rendering (ON THE SERVER SIDE).
However, this panelGroup is not part of rendering. So, my code:
<h:panelGroup rendered="#{someOtherCondition}">
<h:form id="securityForm">
<h:panelGroup rendered="#{someCondition}">
......
</h:panelGroup>
</h:form>
</h:panelGroup>
<h:form>
<a4j:jsFunction name="renderOnBusinessErrorEvent" execute="#none" bypassUpdates="true" immediate="true"
render="securityForm">
</a4j:jsFunction>
</h:form>
Before calling renderOnBusinessErrorEvent() I'm changing the value of someOtherCondition from true to false, but I don't rerender this element. Actually, on the server side this element is already missing. Looks like it's JSF feature, but is it specificated somewhere?

CommandButton execution while rendering

Question: How can I prevent the execution of a while the website is rendering?
Thats where my Button sits:
<p:dialog widgetVar="newComment" height="200" width="500">
<h:form>
<h:panelGrid>
<h:outputText value="#{commentDialog.username}" />
<h:inputTextarea id="in_text" value="#{commentDialog.text}" />
<p:message for="in_text" />
</h:panelGrid>
<p:commandButton validateClient="true" value="Abschicken" ajax="true"
actionListener="#{popupRequestView.update}" action="PF('newComment').hide();update_popup();" />
</h:form>
</p:dialog>
The action attribute is intented to execute a backing bean action method on click, not to print some JavaScript code (which of course get executed immediately
You perhaps meant to use onclick or oncomplete instead. Like as in basic HTML, those on* attributes are intented to execute some JavaScript code during the specified HTML event ("click", "complete", etc).
oncomplete="PF('newComment').hide();update_popup();"
Another cause not visible in the information provided so far is that you forgot to register the p: XML namespace. Any <p:xxx> tags would then be printed as if it's plain text. Verify if a parent element somewhere in the markup has this:
xmlns:p="http://primefaces.org/ui"
Regardless, taking a JSF pause and learning some basic HTML/JavaScript wouldn't be a bad idea. After all, JSF is "just" a HTML/CSS/JS code generator.
you must use primefaces ajaxStatus to prevent click on button while rendering and execute ajax
ajaxStatus in primefaces showcase

JSF dynamically include src in "ui:include src="#{bean.pagePath}"

I tried to include multiple source page path using ui:include tag in different tabs. The problem is when i gave the source page path as static one means that page will be shown but if give the source page path from backing bean mean it won't include the page.
Here is my code
template.xhtml:
<p:layoutUnit position="center" id="layoutCenter">
<h:form id="tempFormId">
<p:tabView value="#{multiTabBean.tabsList}" var="useCase"
activeIndex="#{multiTabBean.activeTabIndex}">
<p:tab title="#{useCase.title}" closable="true">
<f:subview>
<h:panelGroup id="mainTempPanelGroupId" layout="block">
<ui:include src="#{useCase.path}" />
</h:panelGroup>
</f:subview>
</p:tab>
</p:tabView>
</h:form>
</p:layoutUnit>
bean:
public String menuAction() {
menuBtnRendered = true;
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
selectedModuleViewId = externalContext.getRequestParameterMap().get(
"moduleViewId");
tabsList.add(new Tab(getTabId(selectedModuleViewId),
selectedModuleViewId, getModulePath(selectedModuleViewId)));
return null;
}
I'm using #ViewScoped.
<ui:include> runs during view build time (when XHTML is turned into JSF component tree). <p:tabView> runs during view render time (when JSF component tree needs to produce HTML).
So, <p:tabView var> isn't available when <ui:include> runs. This problem is detailed in this answer: JSTL in JSF2 Facelets... makes sense? (<ui:include> is a taghandler and has hence same lifecycle as JSTL tags).
You can solve this to a certain degree by using <c:forEach> to produce <p:tab>s instead of <p:tabView value>.
<p:tabView activeIndex="#{multiTabBean.activeTabIndex}">
<c:forEach items="#{multiTabBean.tabsList}" var="useCase" varStatus="loop">
<p:tab title="#{useCase.title}" closable="true">
<f:subview id="tab_#{loop.index}">
<h:panelGroup id="mainTempPanelGroupId" layout="block">
<ui:include src="#{useCase.path}" />
</h:panelGroup>
</f:subview>
</p:tab>
</c:forEach>
</p:tabView>
It's by the way interesting to see that you somehow used <f:subview> in your initial attempt which is completely useless over there (already taken into account by <p:tabView var>), but it's actually helpful in here (it creates a new NamingContainer around the tab content).
The above Community's answer hasn't worked for dynamic tabView
<p:tabView dynamic="true" ...
If i use dynamic="true" and c:foreach for tabs, when i add or remove a tab, do update #tabViewId, the tabview will reload "All content of existed tabs" => this is not the way to attribute "dynamic" work, it's not lazy.
My project has a problem with this, i had to customize the method encodeEnd of TabViewRenderer and do something else, but it's not simple.
I wondering whether there is a way to include XHTML templates at rendered time?

PrimeFaces BlockUI does not work

I have a JSF page with one button. When button clicked I redirect another page after doing some database process. I want to use BlockUI because redirecting take some time. I added primeface BlockUI component but it do not work for me. I looked PrimeFaces showcase page but I can not do.
My JSF page (xhtml)
<h:body>
<h:form id="form1">
<div align="center">
<p:button id="btn1" value="database" outcome="database" />
<p:blockUI block="form1" trigger="btn1">
<p>Database process</p><br />
<p:graphicImage value="http://www.primefaces.org/showcase/images/loading.gif"/>
</p:blockUI>
</div>
</h:form>
</h:body>
BlockUI worked after I changed p:button with p:commandButton
<p:commandButton id="btn2" value="database" action="#{class.func()}" />
and my func() is
public void func()
{
return "database.xhtml";
}
Try using p:commandButton instead p:button and you can add actionListener and in listener method you can add logic for redirection or simply return name of view component

why JSF 2.0 "rendered" does not work without refreshing the page?

When I click a method to render a part of the page, it does not change anything until I manually refresh the page.
Here is the bean:
boolean showPage = true;
public boolean getShowPage(){
return showPage;
}
Here is the view:
<h:form>
<p:commandButton value="Click" action="#{bean.hideContents()}" />
</h:form>
<p:panel rendered="#{bean.showPage}">
Contents
</p:panel>
The panel gets hidden when I manually refresh the page, otherwise it does not.
How is this caused and how can I solve it?
You need to update a parent component of the conditionally rendered component. You can do that by specifying its client ID in the update attribute of the <p:commandButton>:
<h:form>
<p:commandButton value="Click" action="#{bean.hideContents}" update=":panel" />
</h:form>
<h:panelGroup id="panel">
<p:panel rendered="#{bean.showPage}">
Contents
</p:panel>
</h:panelGroup>
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?

Resources