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.
Related
This question already has answers here:
Invoke JSF managed bean action on page load
(4 answers)
Closed 7 years ago.
Is there an autoload command within JSF or PrimeFaces?
I have a JSF template that I use for my facelets:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
template="template.xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:form>
<p:remoteCommand name="onload" action="#{mainMenuBean.setMenuCategories}" autoRun="true" />
</h:form>
<ui:define name="west">
<ui:include src="mainmenu.xhtml" />
</ui:define>
<ui:define name="center">
<p:outputLabel value="Zentrum" />
<h:form>
<p:remoteCommand name="rc" update="msgs" actionListener="#{mainMenuBean.setMenuCategories()}" />
<p:growl id="msgs" showDetail="true" />
<p:commandButton type="button" onclick="rc()" value="Execute" icon="ui-icon-refresh" />
</h:form>
</ui:define>
</ui:composition>
Now the p:remoteCommand does not work for some reason. Is there are command that I could place instead of p:remoteCommand to automatically execute some bean method everytime it gets loaded?
JSF 2.2 has viewAction, which can be executed on each load or on each get (and skipped on postbacks). It's placed in meta part of page:
<f:meta>
<f:viewAction action="#{anyBean.anyAction}"/>
</f:meta>
edit: mind that this is an action component, so it's execution will depend on any preceding validations / conversions being successful.
I have a <ui:composition> that contains a few elements with explicit ids and some ajax events which reference these ids for partial processing/updating. I encapsulated this fragment of xhtml inside the composition simply so I could use it in a few different places without having to duplicate the code. However, when I use the composition (with <ui:include>) more than once inside a page, I get duplicate id exceptions. It seems JSF is not wrapping each composition inside its own naming container (like <ui:component> does).
Is there a simple way to wrap my composition inside its own naming container?
Or do I have to use a composite component every time I want to reuse xhtml fragments inside a common naming container?
Depending on the purpose of the <ui:include> template, you've several options:
Use <f:subview>. It creates another NamingContainer context (like as <h:form>, <h:dataTable>, and friends all do):
<f:subview id="top">
<ui:include src="/WEB-INF/includes/some.xhtml" />
</f:subview>
...
<f:subview id="bottom">
<ui:include src="/WEB-INF/includes/some.xhtml" />
</f:subview>
The components definied in some.xhtml will end up getting respectively top: and bottom: prefix in their ID.
Turn it into a tagfile which requires an id attribute.
<my:some id="top" />
...
<my:some id="bottom" />
And use that ID to prefix the ID of the components in the composition.
<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:someComponent id="#{id}_some" />
<h:otherComponent id="#{id}_other" />
...
<ui:composition>
Turn it into a composite component. Composite components are inherently already a NamingContainer, so their id attribute is optional. Basically, replace
<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"
>
...
<ui:composition>
by
<ui:component
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"
xmlns:cc="http://java.sun.com/jsf/composite"
>
<cc:interface>
<!-- This is optional. -->
</cc:interface>
<cc:implementation>
...
<h:someComponent id="some" />
<h:otherComponent id="other" />
...
</cc:implementation>
<ui:component>
This way you can use it as follows:
<my:some id="top" />
...
<my:some id="bottom" />
The components definied in <cc:implementation> will end up getting respectively top: and bottom: prefix in their ID (note again, the composite component's id attribute is optional, JSF will otherwise autogenerate one).
See also:
When to use <ui:include>, tag files, composite components and/or custom components?
When you include more than once the same ui:composition the id are duplicated. The solution is to specifiy a particular ui:param within the ui:include.
Assuming you're including mycomposition.xhtml you can do something similar:
<ui:include src="mycomposition.xhtml">
<ui:param name="idPrefix" value="first"/>
</ui:include>
...
<ui:include src="mycomposition.xhtml">
<ui:param name="idPrefix" value="second"/>
</ui:include>
Then in the mycomposition.xhtml you should declare the ids as follows (for instance a h:outputText):
<h:outputText id="#{idPrefix}_text" value="My Awesome Text here"/>
Now you can reference the id in the rest of yout page as #{idPrefix}_text.
p:commandLinks with ids cl1 and cl2 do not fire actions. There is nothing on Tomcat console, nothing on Firebug console.
Where should i look for the problem in such situations, i think i am totally desperate without any error or exception, in both consoles.
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:o="http://openfaces.org/"
xmlns:p="http://primefaces.org/ui">
<h:form>
<ui:repeat var="sharing" value="#{sharingController.myList}">
<ui:repeat var="sharingComment" value="#{sharing.subCommentList}">
<p:commandLink id="cl1" value="" process="#this" action="#{reportController.reportSharingComment(sharingComment)}" style="float:right;" id="sharingComment_alert" styleClass="icon_alert" title="#{msg['label.report']}" update=":messages" >
</p:commandLink>
<p:commandLink value="" id="cl2" process="#this" action="#{sharingController.deleteComment(sharingComment)}" style="float:right;" id="sharingComment_delete" styleClass="icon_delete" title="#{msg['label.delete']}" update="#form :messages">
</p:commandLink>
</ui:repeat>
</ui:repeat>
</h:form>
</ui:composition>
I tried with a concrete list in the nested ui:repeat in post construct then commandlinks was fired, but I must iterate over field lists like sub commentlists of every sharing in myList. I'm loading both myList and for every sharing I load the subCommentlist in a for in post construct, but I still cannot make the commandLinks fire.
h:commandLink / h:commandButton is not being invoked
The 4. point solved:
Putting the bean in the view scope and/or making sure that you load the data model in (post)constructor of the bean (and thus not in the getter method!) should fix it.
I think i came across a bug of #ViewScoped with a4j:commandButton.
I have a very complex form where all actions use a4j, except those that need to upload data.
And depending on the order of the commands the validation of the viewParam breaks.
Here is the working code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j" >
<f:metadata>
<f:viewParam id="viewParam" name="viewParam" value="#{bean.viewParam}" required="true" />
</f:metadata>
<h:head>
<title>Test View Param</title>
</h:head>
<h:body>
<h:message for="viewParam" />
<hr/>
<h:form>
#{bean.viewParam}<br/>
<h:commandButton value="cmdButton" />
<a4j:commandButton value="a4jBtn" execute="#this" render="#form" />
</h:form>
</h:body>
</html>
just click on the a4jBtn and then on the cmdButton to see the problem.
you will see that the parameter is still there! but that the validation fails.
<t:saveState> does not help,
<rich:message> is also not better, but
<h:commandButton value="ajaxBtn" ><f:ajax execute="#this" render="#form" /></h:commandButton>
instead of
<a4j:commandButton value="a4jBtn" execute="#this" render="#form" />
does work correctly!
Using myFaces 2.0.15 and richFaces 4.2.3.Final on Tomcat 6.0.18 and jboss-el 2.0.0.GA.
i could workaround my problem by using f:ajax instead of a4j:commandButton, but maybe you have a better idea, or you could just explain to me what is going wrong?
You basically need to retain the view parameters on synchronous postbacks. As you're using OmniFaces, you could use <o:form> for that.
<o:form includeViewParams="true">
Or as you're already using a view scoped bean, trigger the validation only on non-postbacks.
<f:viewParam ... required="#{not facesContext.postback}" />
Or, as you're using OmniFaces, you could use <o:viewParam> instead which skips the validation/conversion/update on postbacks.
<o:viewParam ... />
I have the following page:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Fire - Registration</title>
</h:head>
<h:body>
<f:view>
<f:event type="preRenderView" listener="#{confirmPasswordResetBean.bindSessionKey()}"/>
</f:view>
<p:growl id="growl" showDetail="true" life="5000" />
<h:form>
<p:panel header="Select your new password">
<h:panelGrid columns="2" cellpadding="5">
<p:outputLabel for="newPassword" value="Type your new password"/>
<p:password id="newPassword"
value="#{confirmPasswordResetBean.firstPassword}"
feedback="true"/>
<p:outputLabel for="retypedPassword" value="Retype your password"/>
<p:password id="retypedPassword"
value="#{confirmPasswordResetBean.secondPassword}"/>
</h:panelGrid>
<p:commandButton id="confirmButton"
value="reset"
action="#{confirmPasswordResetBean.doResetPassword()}"
update=":growl"/>
</p:panel>
</h:form>
</h:body>
The backing bean used above is RequestScoped, and the page itself takes a single parameter (sessionKey)...what I want to do is to:
1. Bind sessionKey to a variable in the backing bean. This is straightforward enough.
2. Use the bound value of sessionKey when executing dedicated logic in the same bean, when the client presses the commandButton.
The problem is that pressing the button starts a new request, which invalidates both the current bean (with the bound value), as well as the external page context...I thus lose all means to get a hold of sessionKey from either the bean or the page parameters...how can I resolve this? I am relatively new to both web programming and JSF, so pardon me if this has an obvious answer.
Either put the bean in the view scope, so that it lives long as you're interacting with the same view, or pass the request parameter by <f:param> to the subsequent requests.
<p:commandButton ...>
<f:param name="sessionKey" value="#{param.sessionKey}" />
</p:commandButton>
By the way, you'd rather have used <f:viewParam> to bind the request parameter to the bean directly.
<f:metadata>
<f:viewParam name="sessionKey" value="#{bean.sessionKey}" />
</f:metadata>
See also:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?