Spring web-flow and JSF templating - jsf

I want to create pages which consist of "header" and "content". I create common.xhtml
<ui:insert name="header">
<ui:include src="commonHeader.xhtml" />
</ui:insert>
<ui:insert name="content">
<ui:include src="commonContent.xhtml" />
</ui:insert>
Then I create two pages (create_user_page.xhtml and search_page.xhtml) which must have the same "header" but different "content"
<ui:composition template="common.xhtml">
<ui:define name="content">
<h1>Content for creating...</h1>
<ui:include src="create.xhtml"/>
</ui:define>
</ui:composition>
and
<ui:composition template="common.xhtml">
<ui:define name="content">
<h1>Content searching...</h1>
<ui:include src="search.xhtml"/>
</ui:define>
</ui:composition>
In my web_flow.xml I have
<view-state id="start_page" view="administrator/main_page.xhtml">
<transition on="create_user" to="create_user_page" />
<transition on="find_user" to="search_page" />
<transition on="back" to="back" />
</view-state>
<view-state id="create_user_page" view="administrator/create_user_page.xhtml">
<transition on="create_user" to="create_user_page" />
<transition on="find_user" to="search_page" />
</view-state>
<view-state id="search_page" view="administrator/search_page.xhtml">
<transition on="create_user" to="create_user_page" />
<transition on="find_user" to="search_page" />
</view-state>
At the main_page.xhtml I have two actions "create_user" and "find_user" (in "header") which lead to pages
create_user_page.xhtml and search_page.xhtml. They have similar "header" and differ in "content". All this works good but I have some questions.
1) It seems that "header" re-rendered every time I get in create_user_page.xhtml or search_page.xhtml, or I am wrong? Is it possible the the "header" will stay without re-rendering and changes will be made only for "content".
2)In my web flow xml I have to duplicate code
<transition on="create_user" to="create_user_page" />
<transition on="find_user" to="search_page" />
for "create_user_page" and "search_page". Is it possible some how to rewrite it keeping in mind that these actions take place in "header" which is the same for these two pages.

JSF templating will always re-render your header/footer. Personally I dont think its a problem unless you have something really performance-intensive in there. You can avoid re-rendering by:
Using HTML frames http://www.w3schools.com/tags/tag_frameset.asp
Partial rendering - either in your SWF flows (see tag in http://static.springsource.org/spring-webflow/docs/2.0.x/reference/htmlsingle/spring-webflow-reference.html#view-transitions), or something like PrimeFaces partial rendering
You will probably have to redesign your XHTML and flows if you use either approach - effectively your partial rendering will replace flow definition. Something like:
<h:commandLink value="go to search page" actionListener="#{myBean.goToSearchPage}" update="content"></h:commandLink>
<h:commandLink value="go to another page" actionListener="#{myBean.goToAnotherPage}" update="content"></h:commandLink>
<h:panelGroup id="content">
<h:panelGroup id="search-page" rendered="#{myBean.isThisSearchPage}">
<!-- search page contents here -->
</h:panelGroup>
<h:panelGroup id="another-page" rendered="#{myBean.isThisAnotherPage}">
<!-- another page contents here -->
</h:panelGroup>
</h:panelGroup>
The above approach is definitely much less maintainable and not-recommended. Use standard SWF instead and rerender your header/footer whenever view changes. You can still use partial rendering within SWF view to respond to user's input without rerendering the whole page.
Regarding the second question: you can use global transitions and flow inheritance. See How to import globaltransitions.xml in myflow.xml?

Related

Every include should refer to other instance

I include a part of the XHTML page to my Web Application. This part can be included multiple times. And that's the problem! Because every include refers to the same java object. That means that every element has the same value. But I want for each include a new Java object. So whats the best way to solve this problem?
Main page with includes:
<ui:composition template="./templates/template.xhtml">
<ui:define name="mainContent">
<ui:include src="include/includeAbleEditor.xhtml">
<ui:param name="includeParam" value="MyClass" />
</ui:include>
<ui:include src="include/includeAbleEditor.xhtml">
<ui:param name="includeParam" value="YourClass" />
</ui:include>
</ui:define>
includAbleEditor.xhtml
<h:commandButton value="#{editorVisibility.evb.value}"
action="#{editorVisibility.evb.toggle}" />
<h:inputTextarea rendered="#{editorVisibility.evb.enabled}" />
This <h:inputTextarea> is an example for my problem. Every included inputTextarea has a toggle button. By clicking the button the textarea should be shown or hidden. But because of the same reference of the boolean value all <h:inputTextarea> will always have the same rendered value.
Do you have any suggestions?
Thanks a lot!
You'll have to hold as many instances of editorVisibility.evb as you have editors. You could for example create a List<TypeOfEvb> evbList in your EditorVisibility bean, and pass only one element to the <ui:include> as a <ui:param>:
Main page
<ui:include src="include/includeAbleEditor.xhtml">
<ui:param name="includeParam" value="MyClass" />
<ui:param name="evb" value="#{editorVisibility.evbList[0]}" />
</ui:include>
includAbleEditor.xhtml
<h:commandButton value="#{evb.value}"
action="#{evb.toggle}" />
<h:inputTextarea rendered="#{evb.enabled}" />
You could also create a composite component.
See also:
http://www.mkyong.com/jsf2/composite-components-in-jsf-2-0/

Jsf 2.0-<ui:include>xhtml included always even if rendered is false

I have a home page xhtml where i am including 3 child xhtml based on conditions.
The issue i am facing is , whatever be the scenario,Book.xhtml always gets invoked.
I changed the rendered condition to false or move out to another condition, but the file always gets invoked Due to which its backing bean also is invoked causing unwanted overhead.
Please provide me a solution
<ui:composition template="/xhtml/baseLayout.xhtml">
<ui:define name="browserTitle">
<h:outputText value="HOME PAGE" />
</ui:define>
<ui:define name="header">
<ui:include src="/xhtml/header.xhtml" />
</ui:define>
<ui:define name="bodyContent">
<h:panelGrid width="100%"
rendered="#{pogcore:isRoleAuthorized(BUNDLE.SUPER)}" >
<ui:include src="/xhtml/SuperUser.xhtml" />
</h:panelGrid>
<h:panelGrid width="100%"
rendered="#{pogcore:isRoleAuthorized(BUNDLE.MAINTENANCE)}" >
<ui:include src="/xhtml/Maintenance.xhtml" />
</h:panelGrid>
<h:panelGrid width="100%"
rendered="#{pogcore:isRoleAuthorized(BUNDLE.PRINT)}">
<ui:include src="/xhtml/Book.xhtml" />
</h:panelGrid>
</ui:define>
</ui:composition>
This is happening due to lifecycle of jsf. JSF UIComponents are evaluated during view render time where as jstl tags are evaluated at build time.
So when you use rendered attribute of h:panelGrid it is too late to not invoke managed beans under the included page. To resolve this try having conditions using jstl tag, the following should work for you.
<c:if test="#{bean.yourCondition}">
<h:panelGrid width="100%">
<h:outputText value="#{bean.yourCondition}"/> <!--if this is not getting printed there is smtg wrong with your condition, ensure the syntax, the method signature is correct-->
<ui:include src="/xhtml/Book.xhtml" />
</h:panelGrid>
</c:if>
<c:if test="#{!bean.yourCondition}">
<h:outputText value="#{bean.yourCondition}"/> <!--This should print false-->
</c:if>
The document below describes the details of jstl and jsf lifecycle.
http://www.znetdevelopment.com/blogs/2008/10/18/jstl-with-jsffacelets/
Check the following document to see another way to solve this without using jstl tags.
http://pilhuhn.blogspot.com/2009/12/facelets-uiinclude-considered-powerful.html
Do this:
Always include the sub pages
Put the panelGrid (with the rendered) inside the page that you always include
Why ? Because the inclusion is performed before the rendered is evaluated.

What is the real conceptual difference between ui:decorate and ui:include?

It occurs ago me that ui:decorate is functionally the same as ui:include except that you can also pass ui:param and ui:define to the included file.
Am I crazy?
EDIT : Although in fact you can pass ui:param to a ui:include file too, it turns out I am already doing it. Maybe you can pass a ui:define as well, I will check and edit here.
The main difference between <ui:include> and <ui:decorate> is that the <ui:decorate> is intended to allow insertion of user-defined template components, while the <ui:include> is intended to include an existing and already-predefined template.
This indeed means that the <ui:decorate> supports <ui:define> for user-defined template components in its body and can insert it at the <ui:insert> place inside the template.
Here's a -somewhat clumsy- example to show where it can be used:
/WEB-INF/templates/field.xhtml
<ui:composition
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:outputLabel for="#{id}" value="#{label}" />
<ui:insert name="input" />
<h:message id="#{id}_message" for="#{id}" />
</ui:composition>
/page.xhtml
<h:panelGrid columns="3">
<ui:decorate template="/WEB-INF/templates/field.xhtml">
<ui:param name="label" value="Foo" />
<ui:param name="id" value="foo" />
<ui:define name="input">
<h:inputText id="foo" value="#{bean.foo}" required="true" />
</ui:define>
</ui:decorate>
<ui:decorate template="/WEB-INF/templates/field.xhtml">
<ui:param name="label" value="Bar" />
<ui:param name="id" value="bar" />
<ui:define name="input">
<h:selectBooleanCheckbox id="bar" value="#{bean.bar}" required="true" />
</ui:define>
</ui:decorate>
...
</h:panelGrid>
Note that it renders the components nicely in each cell of the panel grid. Again, this particular example is pretty clumsy, I'd just have used a tag file instead. Only if it was a larger section, e.g. a whole form whose e.g. its header or footer should be customizable, then an <ui:decorate> would have been appropriate.
Another major advantage of <ui:decorate> is that it allows you to use a composite component with a template. See also Is it possible to use template with composite component in JSF 2?

Parameterization of facelet custom tag

I have created facelet template:
left-right.xhtml
<ui:composition>
<ui:include name="left" />
<hr />
<ui:include name="right" />
</ui:composition>
After, if I use this template with ui:decorate it works fine:
index.xhtml
<ui:decorate template="left-right.xhtml">
<ui:define name="left">FOO</ui:define>
<ui:define name="right">BAR</ui:define>
</ui:decorate>
BUT, if I use this template as custom facelet tag it does not works.
custom-taglib.xml
<facelet-taglib>
<tag>
<tag-name>leftright</tag-name>
<source>left-right.xhtml</source>
</tag>
</facelet-taglib>
index.xhtml
<custom:leftright>
<ui:define name="left">FOO</ui:define>
<ui:define name="right">BAR</ui:define>
</custom:leftright>
The content inside ui:define tags is not included into template :(
So, question is how can I parameterise facelet template if it renders as facelet custom tag?
(note that you have a syntax error in your left-right.xhtml, you should be using <ui:insert> instead of <ui:include>, but I'll assume it to be just careless oversimplification)
A tag file cannot be treated as a template client. You need to approach it differently depending on the concrete functional requirement. If you're on JSF 2.x, then a composite component would be the closest which you need. You could define the parts as <f:facet> and render them by <cc:renderFacet> in the composite implementation.
E.g.
/resources/custom/leftRight.xhtml
<cc:interface>
<cc:facet name="left" required="true" />
<cc:facet name="right" required="true" />
</cc:interface>
<cc:implementation>
<cc:renderFacet name="left" />
<hr />
<cc:renderFacet name="right" />
</cc:implementation>
Usage:
<custom:leftRight>
<f:facet name="left">FOO</f:facet>
<f:facet name="right">FOO</f:facet>
</custom:leftRight>
But if you're still on JSF 1.x, you cannot create a composite component. You'd need to stick to <ui:decorate>.
See also:
When to use <ui:include>, tag files, composite components and/or custom components?

how to use rich:effect with a4j:include

i've got this jsf code
<f:view>
<rich:page pageTitle="My Page" markupType="xhtml">
...
<rich:panel id="content">
<a4j:include viewId="#{MyBacking.viewId}" />
</rich:panel>
and after trying a number of different ways, I've still not managed to place the following correctly in my code:
<rich:effect for="window" event="onload" type="BlindDown" params="targetId:'<different tags depending on where I place this tag>',duration:2.8" />
My aim is to have the changed element in the a4j:included part of the page change but with the effect in use. I've tried putting it in my included page, or just after the f:view and rich:page tags in the calling page but to no avail. The demo doesn't take includes into account so I'm a bit stuck. Thanks
Just target the a panel inside the rich:panel: targetId:'contentPanel'
and then
<rich:panel ..>
<h:panelGroup layout="block" id="contentPanel">
<a4j:include viewId="#{MyBacking.viewId}">
<ui:param name="targetIdParam" value="putYourTargetIdHere" />
</a4j:include>
<h:panelGroup>
</rich:panel>

Resources