Trying to display the pages dynamically based on the dropdown list value.All the associated components are rendering properly.When I bean is in view scope the validations are not triggering whereas the samething is working fine with session scope.Could anyone please help me to resolve the issue?
Here follows my code of Main.xhtml This page contains the dropdownlist.Based on the dropdown value dynamically including the pages.
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="#{templates.standard}">
<ui:define name="contentArea">
<c:choose>
<c:when test="#{testBean.value == '1'}">
<h:panelGroup>
<ui:include src="Page1.xhtml" />
</h:panelGroup>
</c:when>
<c:when test="#{testBean.value == '2'}">
<h:panelGroup>
<ui:include src="Page2.xhtml" />
</h:panelGroup>
</c:when>
</c:choose>
</ui:define>
</ui:composition>
</html>
The below Page1.xhtml will be included dynamically in Main.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:panelGroup>
<h:inputText value="#{testBean1.date}"
id="date"
required="true" requiredMessage="Enter Valid date">
<f:validator validatorId="test.TestDateValidator" />
</h:inputText>
</h:panelGroup>
<h:panelGroup>
<h:message for="date"/>
</h:panelGroup>
View scoped beans are stored in the JSF view. The JSF view is only available when it has been built. Taghandlers like JSTL <c:xxx> run during view build time. They thus run before the JSF view is available. So, when you bind a property of a view scoped bean to a JSTL tag attribute, then it would not refer the view scoped bean instance in the JSF view, but instead refer a freshly created one, with all properties set to default.
So, basically, you end up with two different instances of a view scoped bean on a per-request basis. One which is used during restoring the view (the one which is freshly recreated on every form submit) and another one which is used during processing the form submit (the one which was actually stored in the view scope).
This chicken-egg issue is already reported as JSF issue 1492 and fixed for the upcoming JSF 2.2.
Until then, your best bet is to create a separate request scoped bean and let the include condition depend on a request parameter which is injected by #ManagedProperty, or to turn off partial state saving (which may however have memory/performance implications). Note that the <ui:include> also runs during view build time, so wrapping it in a JSF component with the rendered attribute won't help anything as it is evaluated during view render time.
See also:
JSTL in JSF2 Facelets... makes sense?
Communication in JSF 2.0 - #ViewScoped fails in taghandlers
Related
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
I want to create a composite component which adds some common meta data to views, like:
<viewController:metadata controller="orderController"/>
the component:
<composite:interface>
<composite:attribute name="controller" />
</composite:interface>
<composite:implementation>
<f:metadata>
<f:viewParam name="id" value="#{cc.attrs.controller.id}" />
<f:event type="preRenderView"
listener="#{cc.attrs.controller.initConversation}" />
</f:metadata>
</composite:implementation>
i do similar things to add a button bar to all views and it works fine, but it seems its not possible with f:metadata.
Am i right or is there something wrong with my code?
thanks
This isn't possible. The <f:metadata> has to go in the view associated with the view ID. See also the tag documentation (emphasis mine):
Declare the metadata facet for this view. This must be a child of the <f:view>. This tag must reside within the top level XHTML file for the given viewId, or in a template client, but not in a template. The implementation must insure that the direct child of the facet is a UIPanel, even if there is only one child of the facet. The implementation must set the id of the UIPanel to be the value of the UIViewRoot.METADATA_FACET_NAME symbolic constant.
I'm doing a page with jsf 2.0 and i wanna do something like this:
<f:metadata>
<f:viewParam name="id" value="${id}" />
<f:event type="preRenderView" listener="#{controller.initPage(id)}"/>
</f:metadata>
....(Some code)....
<c:forEach items="#{bean.listLoadedByInitPage}" var="var">
#{var.something}
</c:forEach>
The method initPage(id) must load list in the bean. But seems that method is called after than c:forEach loads items not before. Any ideas?
JSTL tags runs during view build time. The <f:event type="preRenderView"> runs right before view render time. In other words, <c:forEach> runs before <f:event>. So, this behaviour is fully expected.
You have 2 options:
Use #ManagedProperty instead of <f:viewParam>, or when the bean is in the view scope or broader, grab it manually from ExternalContext#getRequestParameterMap() inside #PostConstruct. And, use #PostConstruct instead of <f:event type="preRenderView">. Yes, this makes the entire <f:metadata> obsolete. You can safely remove it.
Use a JSF component instead of <c:forEach> tag, such as <ui:repeat>.
See also:
JSTL in JSF2 Facelets... makes sense?
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>
I have a login page in a web application project:
<h:form>
<h:messages />
<h:inputText label="Username" value="#{login.username}" required="true" />
<h:inputSecret label="Password" value="#{login.pass}" required="true" />
<h:commandButton value="Accedi" action="#{login.check()}" />
</h:form>
When I submit the form, jsf creates three instances of Login class (I've noticed this behavior using debugger). In this way I can't use the username and password in Login.check() method: they are both null.
Besides I've tested another more complex project I've created some time ago and it works fine: only one instance is created. I don't understand where I'm wrong.
Take a look at the managed bean configuration of the login bean (either annotations of the class or in faces-config.xml), specifically its scope. A scope of "none" would have exactly the effect you're observing. The appropriate scope would probably be "request".