how to pass a DOM object (an input) to the handler of the oncomplete event so I can manipulate it's parent?
JSF code:
<p:datatable>
...
<p:column>
<h:inputText id="my_field" value="#{bean.my_field}">
<p:ajax oncomplete="handle_oncomplete( $(this) )" listener="#{bean.handle_change}" />
</h:inputText>
</p:column>
...
</p:datatable>
JS code:
//NOT WORKING
function handle_oncomplete(my_param) {
_parent = my_param.parent();
_parent.css( "background", "#123456");
}
I used my_param.attr('source') to access the DOM object passed:
//WORKING
function handle_oncomplete(my_param) {
_parent = $(my_param.attr('source')).parent();
_parent.css( "background", "#123456");
}
Is there any other way?
EDIT: console.log(my_param.parent()) output
EDIT: Add code to reproduce the issue
<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:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<f:view contentType="text/html" locale="fr" encoding="UTF-8">
<h:head>
</h:head>
<h:body>
<h:form id="dvForm">
<div id="my_id" style="padding: 50px;">
<h:inputText id="my_input">
<p:ajax update="" oncomplete="complete_handler($(this) )"
listener="#{bean.handle_change}" />
</h:inputText>
</div>
</h:form>
<h:outputScript library="primefaces" name="jquery/jquery.js" />
<script type="text/javascript">
function complete_handler(my_param) {
my_obj = my_param.attr('source');
_parent = my_obj.parent();
_parent.css( "background-color", "#123456");
}
</script>
</h:body>
EDIT: the generated html code
<html xmlns="http://www.w3.org/1999/xhtml"><head><link type="text/css" rel="stylesheet"
href="/myproject/javax.faces.resource/theme.css.xhtml?ln=primefaces-aristo" /><script
type="text/javascript"
src="/myproject/javax.faces.resource/jquery/jquery.js.xhtml;jsessionid=5DDDEBBC02044818081D23A267940E72?ln=primefaces">
</script><script
type="text/javascript"
src="/myproject/javax.faces.resource/primefaces.js.xhtml;jsessionid=5DDDEBBC02044818081D23A267940E72?ln=primefaces">
</script></head><body>
<form id="dvForm" name="dvForm" method="post"
action="/myproject/test/t1.xhtml;jsessionid=5DDDEBBC02044818081D23A267940E72"
enctype="application/x-www-form-urlencoded">
<input type="hidden" name="dvForm" value="dvForm" />
<div id="my_id" style="padding: 50px;"><input id="dvForm:my_input" type="text"
name="dvForm:my_input" onchange="PrimeFaces.ab({source:this,event:'valueChange',process:'dvForm:my_input',oncomplete:function(xhr,status,args){complete_handler($(this) );}},
arguments[1]);" /></div><input type="hidden" name="javax.faces.ViewState"
id="javax.faces.ViewState" value="5837380100056002382:-3836335094805954101" autocomplete="off" />
</form>
<script type="text/javascript">
function complete_handler(my_input) {
my_obj = my_input.attr('source');
$(my_obj).parent().css('background-color', "#123456");
}
</script></body>
</html>
Related
I'm trying to invoke an method to update an outputLabel after changing the value selected on my SelectOneMenu. I've already tried all the questions that was answered here, but it's not working. The method on my Managed Bean is not being invoked, I tried to print something on console and doesn't work. There's no Exceptions. I've found this answer
commandButton/commandLink/ajax action/listener method not invoked or input value not updated
but I don't know if I'm missing something, probably I've already checked all the adressed points in the answer.
My SelectOneMenu code is
<h:selectOneMenu id="creditos" value="#{comprarCreditoBean.quantidadeCreditos}" required="true" requiredMessage=" *Campo obrigatório!">
<f:selectItem itemLabel="Selecione uma opção" noSelectionOption="true"/>
<f:selectItem itemValue="30" itemLabel="30 Créditos" />
<f:selectItem itemValue="60" itemLabel="60 Créditos" />
<f:selectItem itemValue="90" itemLabel="90 Créditos" />
<f:selectItem itemValue="120" itemLabel="120 Créditos" />
<f:ajax event="change"
execute="formulario"
render="valPagamento"
listener="#{comprarCreditoBean.tratarMudancaCreditos}"/>
</h:selectOneMenu>
<br />
</h:panelGroup>
<h:message class="mensagens" for="creditos" />
<h:outputLabel value="Total a Pagar: "/>
<h:outputLabel id="valPagamento" value="#{comprarCreditoBean.valorPagamento}" required="true" requiredMessage=" *Campo obrigatório!">
<f:convertNumber currencySymbol="R$" type="currency"/>
</h:outputLabel>
The master template is using the <h:head> and the selectOneMenu is already inside a <h:form> component.
On my ManagedBean the following method should be invoked:
public void tratarMudancaCreditos(AjaxBehaviorEvent evento){
System.out.println("Hi");
System.out.println(this.quantidadeCreditos);
if(this.quantidadeCreditos == 30){
this.valorPagamento = 1.0;
}else if(this.quantidadeCreditos == 60){
this.valorPagamento = 2.0;
}else if(this.quantidadeCreditos == 90){
this.valorPagamento = 3.0;
}else if(this.quantidadeCreditos == 120) {
this.valorPagamento = 4.0;
}
}
I'm really worried about the way I'm trying to update the value that should be updated on my page, if the method is not being invoked, nothing I'm doing inside it would work.
I'm using Tomcat 8.0 and JSF 2.0 if it's relevant
#Edit1
I'm using a template, so I'm posting a relevant code from my template.
First, on the page where's the SelecteOneMenu is situated, I have the following code just to identify that I'm using template.
<ui:composition template="/Template.xhtml"
xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:b="http://bootsfaces.net/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html" version="2.0">
In the same page, I have
<ui:define name="corpo-da-pagina">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><span class="tituloPanel">Comprar Créditos</span></h3>
</div>
<div class="panel-body" align="center">
<h:form id="formulario">
<h:panelGrid columns="3">
<h:outputLabel value="Quantidade de Créditos (1 Minuto = 1 crédito): "/>
<h:panelGroup>
<h:selectOneMenu id="creditos" value="#{comprarCreditoBean.quantidadeCreditos}" required="true" requiredMessage=" *Campo obrigatório!">
<f:selectItem itemLabel="Selecione uma opção" noSelectionOption="true"/>
<f:selectItem itemValue="30" itemLabel="30 Créditos" />
<f:selectItem itemValue="60" itemLabel="60 Créditos" />
<f:selectItem itemValue="90" itemLabel="90 Créditos" />
<f:selectItem itemValue="120" itemLabel="120 Créditos" />
<f:ajax event="change"
execute="formulario"
render="valPagamento"
listener="#{comprarCreditoBean.tratarMudancaCreditos}"/>
</h:selectOneMenu>
<br />
</h:panelGroup>
<h:message class="mensagens" for="creditos" />
<h:outputLabel value="Total a Pagar: "/>
<h:outputLabel id="valPagamento" value="#{comprarCreditoBean.valorPagamento}" required="true" requiredMessage=" *Campo obrigatório!">
<f:convertNumber currencySymbol="R$" type="currency"/>
</h:outputLabel>
<h:commandButton class="btn btn-default" value="Comprar" action="#{comprarCreditoBean.efetuarCompra}"/>
<h:button class="btn btn-default" value="Voltar" outcome="paginaPrincipal"/>
</h:form>
This is basically the construction from my page, other things are fine.
My template.xhtml is defined on this code:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:b="http://bootsfaces.net/ui"
xmlns:h="http://java.sun.com/jsf/html" version="2.0">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<meta name="viewport" content="width=device-width" />
<!-- CSS -->
<link rel="stylesheet" type="text/css" href="resources/css/estilo.css" />
<link rel="stylesheet" type="text/css" href="resources/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="resources/css/bootstrap.css" />
<!-- JS -->
<script src="resources/js/jquery.js"></script>
<script src="resources/js/bootstrap.min.js"></script>
<!-- Ícone Navegador -->
<link href="resources/imagens/icone.png" rel="shortcut icon" type="image/x-icon" />
<title>e-BlueCard</title>
</h:head>
<h:body>
<f:view>
<div id="header" align="center">
<ui:include src="/menu.xhtml" />
</div>
<ui:insert name="corpo-da-pagina">Conteúdo</ui:insert>
<div class="well well-sm" align="center">
<div id="footer" align="center">
<span id="rodape">2016. Análise e Desenvolvimento de Sistemas - e-blue Card. Todos os direitos reservados.</span>
</div>
</div>
</f:view>
</h:body>
#Edit 2
I've found an interesting thing. I've tried to open on Chrome browser, and using the F12 to see the console, always when I tried to change the value from the SelectOneMenu, the console from browser shows the following error:
Error caught by Chrome
You should replace <jsp:root ...> in your template with <html ...></html> like this
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
OTHER LIBRARIES HERE
>
<h:head>
HEADER CONTENT HERE
</h:head>
<h:body>
BODY CONTENT HERE
</h:body>
</html>
Here is a link that can help you understand JSF templates
I have a form submited with ajax which normally must execute the removeArticle function. The problem is when I'm clicking the button, the function is never called and a beautiful error message is returned (displayed with alert) telling me : "serverError: class javax.ejb.NoSuchEJBException CORBA OBJECT_NOT_EXIST 9998 Maybe; nested exception is: org.omg.CORBA.OBJECT_NOT_EXIST: vmcid: 0x2000 minor code: 1806 completed: Maybe". I'm using in another part a similar (almost) form for adding a cocktail. When I place my removeArticle calling into this other form it's executed ...
My code is the following :
<?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">
<ui:composition template="template/common/commonLayout.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:component="http://java.sun.com/jsf/composite/component"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core">
<ui:define name="title">Panier</ui:define>
<ui:define name="content">
<c:if test="#{dataManagedBean.cartLength > 0}">
<div id="cart-component">
<h2>Panier</h2>
<div class="well well-small">
<ul class="thumbnails">
<ui:repeat value = "#{dataManagedBean.cartContent}" var = "item" varStatus="status">
<h:form id="cocktail-panier">
<div class="media">
<div class="pull-left media-object span2">
<div class="text-center">
<img src="resources/img/#{item.photoURIName}.#{item.photoURIExt}"
alt="Photo du cocktail #{item.name}"/>
</div>
</div>
<div class="media-body">
<h3 class="media-heading">
#{item.name}
</h3>
<div class="well well-small">
<ul class="thumbnails">
<ui:repeat value="#{dataManagedBean.getCocktailBeverages(dataManagedBean.getCocktailFull(item))}" var="bev" varStatus="status1">
<component:ShowBeverageComponent item="#{bev}"/>
</ui:repeat>
<div class = "span2 right">Quantité : #{dataManagedBean.getQuantityForCocktailInCart(item)}</div><br />
<div class = "span2 right">Prix unitaire : #{item.price} €</div><br />
<div class = "span2 right">Prix total : #{item.price * dataManagedBean.getQuantityForCocktailInCart(item)} €</div>
</ul>
<h:commandButton
title=""
value="Supprimer les articles "
type="button"
actionListener="#{dataManagedBean.removeArticle(item)}">
<f:ajax execute="#form" render="#all" />
</h:commandButton>
<h:inputText id="qty" maxlength="3" value="#{dataManagedBean.qty}" styleClass="input-mini" />
</div>
</div>
</div>
</h:form>
</ui:repeat>
</ul>
</div>
</div>
</c:if>
<li class="thumbnail">
<div class="totalPanier">
<div class="total-cart"> Total: #{dataManagedBean.getCartPrice()}€</div>
<h:button class="totalPanier-button"
image="#{resource['img:btn_valider.png']}"
alt="valider" outcome="Form.xhtml" rendered="#{dataManagedBean.cartLength > 0}">
</h:button>
<div class="clear"></div>
</div>
</li>
</ui:define>
</ui:composition>`
HTML Elements IDs shouldn't have "-" like in your: <h:form id="cocktail-panier"> AND <div id="cart-component">, this causes Problems in js. replace all these ids with underscore cart_component, or use Java Style like cartComponent
use commandButton like this:
<h:commandButton
title=""
value="Supprimer les articles "
type="button">
<f:ajax execute="#form" render="#all" listener="#{dataManagedBean.removeArticle(item)}"/>
</h:commandButton>
Ajax-Listener method like:
public final void removeArticle(final YourItemClass item){
you use jstl components. JSTL will run on build time, and if your Bean is requestScoped, then the render / action of commandbutton will not fire.
change your bean (if not) to ViewScope or SessionScope, and use rendered instead of <c:if...
somthing like:
replace this <c:if test="#{dataManagedBean.cartLength > 0}">
width this:
<h:panelGroup display="block" rendered="#{dataManagedBean.cartLength > 0}">
.....
ADDITIONALY:
you use templates. your template should somthing like this:
<!DOCTYPE html>
<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:head>
<meta charset="UTF-8" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<h:outputStylesheet name="stylesheet.css"/>
<title>${pageTitle}</title>
In your XHTML Page where you use this template, you don't need to declare XML or HTML docType, and use your template directly:
<ui:composition template="template/common/commonLayout.xhtml"
....
Use <h:head> in your template instead of the <head>, else JSF will not include the jsf.js in the document
The problem was the nested ui:repeat ! I replaced my 2 ui:repeat by 2 c:forEach and everything is working fine !
i have main page as that contains interests composite component and links for lazy loaded tabs as follows:
1- profile 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">
<ui:composition template="../templates/application.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:o="http://omnifaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:myapp="http://java.sun.com/jsf/composite/component"
xmlns:p="http://java.sun.com/jsf/passthrough">
<ui:define name="head">
<title>Profile</title>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<link rel="stylesheet" type="text/css" href="#{request.contextPath}/resources/assets/css/jquery/jquery-ui.css" media="screen"/>
<link rel="stylesheet" type="text/css" href="#{request.contextPath}/resources/assets/css/override-jquery.css" media="screen"/>
<style>
li
{
outline: none !important;
}
</style>
</ui:define>
<ui:define name="right-side">
<div class="three-column right">
<myapp:interest bean="#{interestBean}" value="#{interestBean.interest}" id="interestCmp"></myapp:interest>
</div>
</ui:define>
<ui:define name="content">
<div class="tabs">
<ul>
<li><a id="tab1" href="tabs/tab1.xhtml">tab1</a></li>
<li><a id="tab2" href="tabs/tab2.xhtml">tab2</a></li>
</ul>
</div>
<script type="text/javascript">head.ready(function(){$('.tabs').tabs();});</script>
</ui:define>
</ui:composition>
2- interests composite component:
<?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:ui="http://java.sun.com/jsf/facelets" xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface>
<composite:attribute name="id" />
<composite:attribute name="index" />
<composite:attribute name="value" />
<composite:attribute name="bean" />
</composite:interface>
<composite:implementation xmlns:myapp="http://java.sun.com/jsf/composite/component">
<div >
<aside class="interests">
<header class="header-w-flag icon-star">
<h1>Interests</h1>
</header>
<h:form id="interestForm">
<h:panelGroup id="showInterests" layout="block">
<ui:repeat var="interest" value="#{interestBean.getUserInterests()}" >
<div class="interest">
<div class="interest-name">#{interest.interestName}
<h:commandLink action="#{interestBean.deleteInterest(interest)}" rendered="#{permissionBean.isCurrentUser(profileBean.user)}" >
<i class="icon-delete control-icon" style="cursor:pointer;display:none;"></i>
<f:ajax render="#form" execute="#this"></f:ajax>
</h:commandLink></div>
<div class="people-grid">
<ui:repeat var="user" value="#{interestBean.getUsersByInterest(interest.id)}" varStatus="status" >
<h:panelGroup id="interestedUsers">
<a title="#{user.firstName} #{user.lastName}" href="../profile/index.xhtml?id=#{user.id}"><img src="#{applicationBean.avatarBaseURL}#{user.avatarUrl}" alt="#{user.firstName}" /></a>
</h:panelGroup>
</ui:repeat>
</div>
</div>
</ui:repeat>
</h:panelGroup>
</h:form>
</aside>
</div>
</composite:implementation>
</html>
3- the tab1 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:ui="http://java.sun.com/jsf/facelets"
xmlns:o="http://omnifaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:myapp="http://java.sun.com/jsf/composite/component"
xmlns:p="http://java.sun.com/jsf/passthrough">
<div id="tab1">
<!-- feed here -->
<h:panelGroup layout="block" class="posts" id="feedContainer">
<h:form id="profileFeeds">
<ui:repeat var="post" value="#{feedBean.feeds}" varStatus="status" >
<myapp:feedpost value="#{post}" index="{status.index}"></myapp:feedpost>
</ui:repeat>
<h:panelGroup layout="block" rendered="#{feedBean.feeds.size()==0}">
<div class="post blue">
<div class="post-content">
<h1>Nothing</h1>
</div>
</div>
</h:panelGroup>
<div class="post load"><h:commandLink action="#{feedBean.getMoreHomeFeeds()}" styleClass="btn btn-primary btn-small">Show more feeds
<f:ajax render=":feedContainer" ></f:ajax>
</h:commandLink></div>
</h:form>
</h:panelGroup>
</div>
</html>
4- feedpost composite component that is linked from tab1:
<?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:ui="http://java.sun.com/jsf/facelets" xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface>
<composite:attribute name="id" />
<composite:attribute name="index" />
<composite:attribute name="value" />
</composite:interface>
<composite:implementation xmlns:myapp="http://java.sun.com/jsf/composite/component">
<h:panelGroup layout="block" class="post">
<div class="post-content">
<h:panelGroup layout="block">
<h1><h:outputFormat value="#{cc.attrs.value.title}" /></h1>
</h:panelGroup>
tText value="#{baseBean.replaceWithHTMLBreak(cc.attrs.value.note)}" escape="false"/></p>
</h:panelGroup>
</div>
<myapp:comments value="#{cc.attrs.value}"></myapp:comments>
</h:panelGroup>
</composite:implementation>
</html>
5- comments composite component that is linked from feedpost component:
<?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:ui="http://java.sun.com/jsf/facelets" xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface>
<composite:attribute name="id" />
<composite:attribute name="index" />
<composite:attribute name="value" />
</composite:interface>
<composite:implementation>
<h:panelGroup layout="block" class="comments" id="feedcomments">
<div class="actions">
<h:commandLink id="addToInterestLink" value="#{msg['action.addto.interests']}" styleClass="action-like"
action="#{feedBean.addToInterests(cc.attrs.value)}">
<f:ajax execute="#this" render=":interestCmp:interestForm:showInterests"></f:ajax>
</h:commandLink>
</div>
</h:panelGroup>
</composite:implementation>
</html>
when clicking on tab1 link (lazy loaded jquery tab) that contains the comments composite component that has the link to render interests div in interest component, i am getting following exception:
<f:ajax> contains an unknown id ':interestCmp:interestForm:showInterests' - cannot locate it in the context of the component addToInterestLink
NOTE: one workaround i have found for the issue is to add the tab1 content statically to the page instead of linking it.
please advise how to fix that.
Okay, in a nutshell and somewhat simplified (composite components actually don't play a role in the problem), your problem is here:
profile.xhtml:
<my:composite id="interestCmp"> <!-- Yes, invalid code; just to summarize. -->
<h:form id="interestForm">
<h:panelGroup id="showInterests">
...
</h:panelGroup>
</h:form>
</my:composite>
<div class="tabs">
<ul>
<li><a id="tab1" href="tabs/tab1.xhtml">tab1</a></li>
<li><a id="tab2" href="tabs/tab2.xhtml">tab2</a></li>
</ul>
</div>
<script>head.ready(function(){$('.tabs').tabs();});</script>
And somewhere in tab1.xhtml
<h:form id="profileFeeds">
<h:commandLink value="Add">
<f:ajax render=":interestCmp:interestForm:showInterests" />
</h:commandLink>
</h:form>
You're thus using jQuery UI tabs to have a tabbed panel with dynamic content. However, the tab page tab1.xhtml doesn't share the same JSF view as the main page profile.xhtml. It are physically completely distinct views. That totally explains why the <f:ajax> couldn't find the desired component in the component tree (the current view). It can only see components which are contained in tab1.xhtml itself. It doesn't see those of profile.xhtml. It can't even see those in tab2.xhtml.
It will only work if you preload tabs by <ui:include> instead of dynamically load them. This way the tab1.xhtml will physically end up in the same view as the desired component. Let's assume that you only need to do that for tab1.xhtml and the tab2.xhtml can be kept dynamically loaded. This should then solve your problem:
<div class="tabs">
<ul>
<li><a id="tab1" href="#tab1_page">tab1</a></li>
<li><a id="tab2" href="tabs/tab2.xhtml">tab2</a></li>
</ul>
<div id="tab1_page">
<ui:include src="tabs/tab1.xhtml" />
</div>
</div>
You only need to replace the <?xml...?><!DOCTYPE ...><html xmlns...> and </html> of tab1.xhtml (and actually also tab2.xhtml) by <ui:composition xmlns...> and </ui:composition> respectively. Because otherwise you end up in syntactically invalid HTML.
If you really need to have dynamically/lazily loaded tabs, then you'd better look for a fullworthy JSF component capable of the job, such as PrimeFaces <p:tabView>. Even more, PrimeFaces uses jQuery/UI under the covers for the look'n'feel, so many things will be very simliar to the current approach.
It seems like I am simply unable to grasp, how updating components with Ajax works. I keep on getting an Exception "Cannot find component with identifier ":menu-item-container" referenced from "j_idt12:0:j_idt16:j_idt76"."
This is my code:
<!DOCTYPE html>
<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:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<f:view contentType="text/html">
<h:head>
<title><ui:insert name="pageTitle"></ui:insert></title>
</h:head>
<h:body>
<h:outputStylesheet library="css" name="style.css" />
<div class="menu-navigation">
<ul>
<li>Menu</li>
<ui:repeat var="category"
value="#{restaurantsBean.restaurant.categories}">
<h:form>
<li><p:commandLink update=":menu-item-container">
<div>
#{category.name}
<f:setPropertyActionListener value="#{category.id}"
target="# {restaurantMenuBean.selected}" />
</div>
</p:commandLink></li>
</h:form>
</ui:repeat>
</ul>
</div>
<div id="menu-item-container">
<ui:repeat var="category"
value="#{restaurantsBean.restaurant.categories}">
<p:outputPanel>
<h:panelGroup id="pangroup" layout="block"
rendered="#{restaurantMenuBean.active(category.id)}">
<div class="some-heading">
<h2>#{category.name}</h2>
</div>
<div class="category-description">#{category.description}</div>
<ui:repeat var="item" value="#{category.items}">
<p:outputPanel
rendered="#{restaurantMenuBean.needLightbox(item)}">
<ui:include src="/lightbox-item.xhtml"></ui:include>
</p:outputPanel>
<p:outputPanel
rendered="#{!restaurantMenuBean.needLightbox(item)}">
<ui:include src="/nolightbox-item.xhtml"></ui:include>
</p:outputPanel>
</ui:repeat>
</h:panelGroup>
</p:outputPanel>
</ui:repeat>
</div>
</h:body>
</f:view>
</html>
This is the related area of html source output, which tells me, my "menu-item-container" is right at the root and the update-attribute only needs a separation marker ":" in front of its id.
<div id="menu-item-container"><span id="j_idt17:0:j_idt64"></span><span id="j_idt17:1:j_idt64"><div id="j_idt17:1:pangroup">
<div class="some-heading">
The to-be-updated components are resolved using the algorithm as described in UIViewRoot#findComponent(). It should be obvious that it can find fullworthy JSF components only.
Your menu-item-container is however a plain HTML <div> element and thus unavailable in the JSF component tree.
Replace it by a fullworthy JSF component.
<h:panelGroup id="menu-item-container" layout="block">
The <h:panelGroup> renders by default a <span> and the layout="block" turns it into a <div>.
Could somebody explain me why a4j:commandButton doesn’t reacts at first click in the next scenario?
I have to hit it two times in order to get the action executed…
facelets composite template named principal.xhtml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<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:ui="http://java.sun.com/jsf/facelets"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<f:view contentType="text/html">
<h:head>
<meta http-equiv="content-type" content="text/xhtml; charset=UTF-8" />
</h:head>
<h:body>
<div id="heading">
<ui:insert name="heading">
<ui:include src="/adm/includes/menu.xhtml"/>
</ui:insert>
</div>
<div id="content">
<br />
<a4j:outputPanel ajaxRendered="true">
<ui:insert name="content"/>
</a4j:outputPanel>
<br />
</div>
<div id="footer">
<ui:insert name="footer">
<ui:include src="/adm/includes/footer.xhtml"/>
</ui:insert>
</div>
</h:body>
</f:view>
</html>
The JSF page with the problematic ajax button:
<ui:composition template="/adm/templates/principal.xhtml">
<ui:define name="content">
<rich:panel header="#{msgs.usuariosNuevo}">
<h:form id="formUsuariosNuevo" prependId="false">
<h:panelGrid columns="3">
<h:outputText value="#{msgs.email}" />
<h:inputText value="#{usuarioCtrl.mdl.email}" id="email" />
<h:outputText value="#{msgs.pwd}" />
<h:inputSecret value="#{usuarioCtrl.mdl.pwd}" id="pwd" />
</h:panelGrid>
<a4j:commandButton value="#{msgs.guardar}" action="#{usuarioCtrl.guardarUsuarioAction}" />
</h:form>
</rich:panel>
</ui:define>
</ui:composition>
... and the 'top' toolbar menu menu.xhtml:
<h:form prependId="false" id="formMenu">
<rich:toolbar height="26px">
<rich:dropDownMenu mode="ajax">
<f:facet name="label">
<h:panelGroup>
<h:graphicImage value="/resources/img/icon/usuarios.png" styleClass="pic" width="20" height="20" />
<h:outputText value="Usuarios" />
</h:panelGroup>
</f:facet>
<rich:menuItem label="Nuevo" action="#{menuCtrl.usuariosNuevoAction}" icon="/resources/img/icon/nuevo.png" />
<rich:menuItem label="Gestión" action="#{menuCtrl.usuariosGestionAction}" icon="/resources/img/icon/gestion.png" />
</rich:dropDownMenu>
<!-- Others dropDownsMenu's here ... -->
</rich:toolbar>
</h:form>
thanks!
I think the problem happens when you're using JSF #ManagedBean. You need declare that form bean variable in current flow.
I'm using Richfaces 4.2, Spring-web-flow 2.3.0, Spring 3.1.1
formbean
#RequestScoped
#ManagedBean
public class SearchForm implements Serializable {
private static final long serialVersionUID = 1L;
private String pattern = "Please insert";
public String getPattern() {
return pattern;
}
public void setPattern(String pattern) {
this.pattern = pattern;
}
}
home-flow.xml
<var name="searchForm" class="com.inhouse.web.form.SearchForm"/>
<view-state id="home" view="home.xhtml" model="searchForm">
<transition on="search">
<evaluate expression="searchController.search(requestParameters.pattern)" result="flashScope.searchResults"></evaluate>
</transition>
</view-state>
home.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:sf="http://www.springframework.org/tags/faces"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<ui:composition template="/WEB-INF/layouts/template.xhtml">
<ui:define name="content">
<h:form>
<h:inputText value="#{searchForm.pattern}" />
<a4j:commandButton action="search" value="Search" render="searchResult" immediate="true">
<f:param name="pattern" value="#{searchForm.pattern}"></f:param>
</a4j:commandButton>
</h:form>
<h:panelGroup id="searchResult">
<h:outputText value="#{searchResults}" />
</h:panelGroup>
</ui:define>
</ui:composition>
</html>
Controller
#Controller
public class SearchController {
public String search(String pattern) {
return "this is the search results";
}
}