There are some answers on stackoverflow, but no one fits my needs :(
I'm trying to conditionally build a <ui:param /> for my parent template with JSTL. Something like this:
<ui:composition ... template="template.xhtml">
<c:if test="#{condition}">
<ui:param name="parameter" value="parameterValue" />
</c:if>
<ui:define name="insertName">
{...}
</ui:define>
</ui:composition>
I tried with both namespaces for JSTL: http://java.sun.com/jstl/core and http://java.sun.com/jsp/jstl/core, but neither achieves the wanted behaviour. What should I do?
Funny thing, http://java.sun.com/jstl/core works like it should but INSIDE the <ui:define ...>
Im working with JSF 1.2 on WebLogic 7.
Related
I'm new to JSF, so please forgive me if I'm asking a stupid question.
Suppose I have a common.xhtml file that can be reused by several screens. In fact, the only difference between the screens is the backing bean. For example:
URL: ~/person
<ui:composition template="common.xhtml">
<ui:param name="bean" value="#{personBean}" />
</ui:composition>
URL: ~/vehicle
<ui:composition template="common.xhtml">
<ui:param name="bean" value="#{vehicleBean}" />
</ui:composition>
URL: ~/location
<ui:composition template="common.xhtml">
<ui:param name="bean" value="#{locationBean}" />
</ui:composition>
URL: ~/food
<ui:composition template="common.xhtml">
<ui:param name="bean" value="#{foodBean}" />
</ui:composition>
etc...
Is there a way I can avoid creating all of these trivial xhtml files? Can I somehow dynamically set the backing bean and just point each of these URLs directly to the common.xhtml file?
In a JSF xhtml file, I would like to be able to choose between two different ui:compositions based on some flag. This is illustrated below using a fictional magic:if tag. How can I do this? In other words, what real tag can I use in place of magic:if?
<magic:if test="showOption1">
<ui:composition template="/option1.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:composition>
</magic:if>
<magic:if test="!showOption1">
<ui:composition template="/option2.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:composition>
</magic:if>
In other words, what real tag can I use in place of magic:if?
There's none. The <ui:composition> is the root element. Nothing can end up higher.
You have 2 options:
Do the switch in template attribute itself.
<ui:composition template="/option#{showOption1 ? 1 : 2}.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:composition>
Use <ui:decorate> inside <ui:composition> instead, this one can be wrapped in a <c:if>.
<ui:composition template="/options.xhtml">
<c:if test="#{showOption1}">
<ui:decorate template="/option1.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:decorate>
</c:if>
<c:if test="#{not showOption1}">
<ui:decorate template="/option2.xhtml">
<ui:define name="header">Foo</ui:define>
</ui:decorate>
</c:if>
</ui:composition>
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?
Have JSF 1.2 two pages(one.xhtml and other.xhtml), that are included to the current page by following rule:
...
<c:if test="#{flowScope.Bean.param1}">
<ui:include src="one.xhtml"/>
</c:if>
<c:if test="#{!flowScope.Bean.param1}">
<ui:include src="other.xhtml"/>
</c:if>
...
As far one.xhtml differs from other.xhtml only by action parameters:
one.xhtml:<h:commandLink action="actionOne">
other.xhtml:<h:commandLink action="actionTwo">
Is it possible to use some general xhtml? Instead of one.xhtml and other.xhtml,something like this:
...
<c:if test="#{flowScope.Bean.param1}">
<ui:include src="general.xhtml" param="actionOne"/>
</c:if>
<c:if test="#{!flowScope.Bean.param1}">
<ui:include src="general.xhtml" param="actionTwo"/>
</c:if>
...
thank you for help.
You need to nest <ui:param> inside <ui:include> to pass parameters to the included file.
<ui:include src="general.xhtml">
<ui:param name="action" value="actionOne" />
</ui:include>
and in the include:
<h:commandButton action="#{action}" />
Note that this only supports strings, not action methods. For the latter you would need to upgrade to JSF 2.0 and use composite components.
In addition to BalusC's answer:
Note that this only supports strings,
not action methods. For the latter you
would need to upgrade to JSF 2.0 and
use composite components.
There is a way to do this with JSF 1.2, though it's somewhat ugly:
<ui:include src="general.xhtml">
<ui:param name="actionBean" value="#{myBackingBean}" />
<ui:param name="actionMethod" value="edit" />
</ui:include>
and
<h:commandButton action="#{actionBean[actionMethod]}" />
Due to some custom components which expect a bean name (NOT the bean instance) in their attributes I need to pass the actual bean name between pages. As the bean itself is also used by non-custom components, I would like to avoid using additional ui:param (like described here Passing action in <rich:modalPanel>) since it will essentially specify the same bean.
Is it possible to specify component's action using bean name provided with ui:param?
Basically I am trying to achieve the following:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
template="/template.xhtml">
<ui:param name="beanName" value="sessionBean"/>
...
</ui:composition>
and template.xhtml is
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:a4j="http://richfaces.org/a4j"
template="/someothertemplate.xhtml">
</ui:define name="somename">
<h:form>
<a4j:commandButton value="test" action="#{beanName.delete}"/>
</h:form>
</ui:define>
</ui:composition>
Although delete method is properly defined (verified with action="#{sessionBean.delete}") the above code gives me
javax.faces.FacesException: #{beanName.delete}: javax.el.MethodNotFoundException: /template.xhtml #201,89 action="#{beanName.delete}": Method not found: sessionBean.delete()
You should be able to reference the bean via its scope:
<a4j:commandButton value="test"
action="#{sessionScope[beanName].delete}"/>
<a4j:commandButton value="test" action="#{bean[action]}" />
The params to pass
<ui:param name="bean" value="#{sessionBean}" />
<ui:param name="action" value="delete" />
you can use #{bean['delete']} if your action name is fixed.