I have a Primefaces dialog, and inside it there is a tabView. In this tabView I have 3 tabs, each one called towards ui:include. In the first tab I have a selectOneMenu which defines a property called tipoProprietario from class ProprietarioORM. The navigation between tab is done not by tabs themselves (in this stage they're disabled) but towards commandButtons at bottom of dialog. When I click in a commandButton to pass from the first to second tab tipoProprietario is filled correctly. However, when I click to pass from second do third tab (or even to the first one), I found that the selectItem value is changed to null. Consequently, the tipoProprietario property is also changed to null. Debugging, I saw that first it is called the Select Item listener method and after the tipoProprietario setter.
Can someone explain why this it is happening? How to correct it?
dialog.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<p:dialog id="dlgEdicao" widgetVar="dlgEdicao" resizable="false"
closable="true" modal="true" closeOnEscape="true"
header="#{(proprietarioMB.edicao)? msg['proprietario.titulo.editar']: msg['proprietario.titulo.incluir']}">
<p:tabView id="tabEdicao" widgetVar="tabEdicao" dynamic="true"
styleClass="tabEdicaoProprietario" cache="false"
binding="#{proprietarioMB.tabEdicao}">
<p:tab id="tabProprietario" title="#{msg['proprietario.titulo']}"
disabled="#{not proprietarioMB.edicao}" titleStyleClass="">
<ui:include src="./aba_proprietario.xhtml" />
</p:tab>
<p:tab id="tabEnderecoContato"
title="#{msg['proprietario.titulo.aba.endereco']}"
disabled="#{not proprietarioMB.edicao}">
<ui:include src="./aba_endereco_contato.xhtml" />
</p:tab>
<p:tab id="tabVeiculo"
title="#{msg['proprietario.titulo.aba.veiculo']}"
disabled="#{not proprietarioMB.edicao}">
<ui:include src="./aba_veiculo.xhtml" />
</p:tab>
</p:tabView>
<f:facet name="footer">
<p:commandButton id="btnDialogoAnterior"
value="#{msg['titulo.anterior']}"
rendered="#{not proprietarioMB.edicao}" immediate="true"
disabled="#{not proprietarioMB.btnAnteriorHabilitado}"
actionListener="#{proprietarioMB.doEventClickBtnAnterior}"
update="#this tabEdicao btnDialogoSeguinte btnDialogoConcluir"
style="margin-right: 20px;" />
<p:commandButton id="btnDialogoSeguinte"
value="#{msg['titulo.proximo']} #{(not proprietarioMB.btnConcluirVisivel)? '': 'display: none;'}"
rendered="#{not proprietarioMB.edicao}"
actionListener="#{proprietarioMB.doEventClickBtnSeguinte}"
update="#this tabEdicao btnDialogoAnterior btnDialogoConcluir"
style="margin-right: 20px; #{(not proprietarioMB.btnConcluirVisivel)? '': 'display: none;'}" />
</f:facet>
</p:dialog>
</ui:composition>
aba_proprietario.xhtml (the first tab)
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<p:panel id="pnlDadosProprietario">
<p:focus for="selTipoEdicao" />
<p:fieldset id="fieldDadosProprietario"
legend="#{msg['proprietario.titulo']}"
rendered="#{not empty proprietarioMB.proprietario}">
<p:panelGrid id="pnlDadosProprietarioEdicao">
<p:row>
<p:column>
<p:outputLabel id="lblTipoEdicao"
value="#{msg['proprietario.titulo.tipo']}" for="selTipoEdicao" />
</p:column>
<p:column>
<p:selectOneMenu id="selTipoEdicao"
value="#{proprietarioMB.proprietario.tipoProprietario}"
valueChangeListener="#{proprietarioMB.doEventTipoDocumentoPesquisaChanged}"
immediate="true">
<f:selectItems value="#{proprietarioMB.tiposProprietarios}" />
<p:ajax event="change" update="txtDocumentoEdicao" />
</p:selectOneMenu>
</p:column>
<p:column>
<p:outputLabel id="lblDocumentoEdicao"
value="#{msg['proprietario.titulo.documento']}"
for="txtDocumentoEdicao" />
</p:column>
<p:column>
<p:inputMask id="txtDocumentoEdicao"
value="#{proprietarioMB.proprietario.documento}"
mask="#{proprietarioMB.mascaraDocumento}" />
</p:column>
</p:row>
</p:panelGrid>
</p:fieldset>
</p:panel>
</ui:composition>
The Managed Bean
#ManagedBean
#ViewScoped
public class ProprietarioMB {
private static final String MASCARA_CPF = "999.999.999-99";
private static final String MASCARA_CNPJ = "99.999.999/9999-99";
private static final SelectItem[] tiposProprietarios = new SelectItem[] {
new SelectItem(JURIDICA, JURIDICA.getDescricao()),
new SelectItem(FISICA, FISICA.getDescricao()), };
private ProprietarioORM proprietario;
private String mascaraDocumento;
private TabView tabEdicao;
/**
* Select Item listener method: Changes inputMask mask
*/
public void doEventTipoDocumentoPesquisaChanged(ValueChangeEvent event) {
this.mascaraDocumento = (event.getNewValue() == FISICA) ? MASCARA_CPF
: MASCARA_CNPJ;
}
public void doEventClickBtnAnterior() {
System.out.println("ProprietarioMB.doEventClickBtnAnterior(): "
+ this.tabEdicao.getActiveIndex());
this.tabEdicao.setActiveIndex(this.tabEdicao.getActiveIndex() - 1);
}
public void doEventClickBtnSeguinte() {
System.out.println("ProprietarioMB.doEventClickBtnSeguinte(): "
+ this.tabEdicao.getActiveIndex());
System.out.println("ProprietarioMB.doEventClickBtnSeguinte(): "
+ this.proprietario);
if (this.tabEdicao.getActiveIndex() == 0) {
if (this.validarProprietario()) { // Validation method
this.tabEdicao.setActiveIndex(1);
}
} else if (this.tabEdicao.getActiveIndex() == 1) {
this.tabEdicao.setActiveIndex(2);
}
}
// Other methods + getters & setters
}
ProprietarioORM
public class ProprietarioORM {
private String nome;
private TipoProprietarioEnum tipoProprietario;
// getters & setters
}
It's most likely because of the binding="#{proprietarioMB.tabEdicao}"
For one thing, you don't appear to need the binding at all. Even if you did, you failed to initialize the component in your backing bean, a bug that'll result in the <p:tabView/> attempting to bind to a null variable tabEdicao.
As you don't appear to be using the tabview variable in the backing bean, my recommendation would be to get rid of it. If you really need it, just initialize it:
private TabView tabEdicao = new TabView();
Kolossus:
This issue was resolved when I added the attibute dynamic="true" to dialog. Actually, the real value was dynamic=#{empty proprietarioMB.proprietario}, because I was geting NullPointerException when loading the page. proprietario property is loaded towards #PostConstruct method.
Related
I'm trying to create a ModalPanel from a dataTable (RichFaces 4.5.1, MyFaces 2.2.6, Spring 3.1.1, Tomcat 7.0.27) but I can't.
The modalPanel has values to be displayed based on the selected row in the table. When I click in a commandLink, trigger a actionListener should feed these values (localidadeMB.carregarColecoes()), but it does't work, because the reference to attributes of bean is null (has not been set by the f:setPropertyActionListener located in commandLink).
What was missing?
*page.xhtml
(...)
<f:view>
<h:form id="formConsulta">
<rich:dataTable id="tabela"
value="#{localidadeMB.getLocalidadesPorPalavra()}" var="loc"
rowKeyVar="row" rows="20" width="800px" render="scroller">
<rich:column>
(...)
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value=""/>
</f:facet>
<a4j:commandLink id="editlink" ajaxSingle="true"
oncomplete="#rich:component('modalEditarLocalidade')}.show()"
actionListener="#{localidadeMB.carregarColecoes}"
render="modalEditarLocalidade">
<h:graphicImage value="/img/edit.png"/>
<f:setPropertyActionListener value="#{loc}" target="#{localidadeMB.localidade}" />
</a4j:commandLink>
</rich:column>
</rich:dataTable>
</h:form>
<ui:include src="modalPanel.xhtml" />
*modalPanel.xhtml
<ui:composition>
<rich:popupPanel id="modalEditarLocalidade" autosized="true"
modal="false" resizable="false">
<f:facet name="header">
<h:outputText value="Alterar localidade" />
</f:facet>
<f:facet name="controls">
<h:graphicImage id="modalClosePNG2" value="/img/close1.png"
style="cursor:default;"
onclick="Richfaces.hideModalPanel('modalEditarLocalidade')" />
</f:facet>
<h:form>
<h:outputLabel value="Nome da localidade:" for="nomeLocalidade" />
<h:inputText id="nomeLocalidade"
value="#{localidadeMB.localidade.nome}" required="true"
immediate="true"/>
</h:inputText>
</h:form>
</rich:popupPanel>
</ui:composition>
*ManagedBean
private Localidade localidade;
public void setLocalidade(Localidade l){
this.localidade = l;
}
public void carregarColecoes(ActionEvent action){
System.out.println(localidade.getNome());
***** print NULL *****
}
If you want to set up a variable first and then execute a method you have to use #action for that method, actionListeners are executed first but since both of your methods are actionListeners the localidadeMB.carregarColecoes is executed before the variable is set. (And btw. h:commandLink has no "ajaxSingle" or "oncomplete" attributes.)
With the suggestion of Makhiel and this link I decided.
The xhtml looked like this:
<a4j:commandLink id="editlink" ajaxSingle="true"
oncomplete="#{rich:component('modalEditarLocalidade')}.show()"
action="#{localidadeMB.carregarColecoes}"
render="modalEditarLocalidade">
<h:graphicImage value="/img/edit.png"/>
<f:setPropertyActionListener value="#{loc}"
target="#{localidadeMB.localidade}" />
</a4j:commandLink>
and ManagedBean like this:
public String carregarColecoes(){
(....)
}
I'm having problems with a form that is rendered by a booleanButtom on PrimeFaces 3.5
the form appear as expected but when I commit the values of the field come null.
The code of the pag:`
<p:panelGrid>
<p:row>
<p:column>
<h:form id="city">
<p:panelGrid columns="2">
<h:outputText value="Name: "/>
<p:inputText label="Name" value="#{managedBean.city.name}"/>
<h:outputText value="Status: "/>
<p:selectBooleanButton value="#{managedBean.city.status}" onLabel="Enable" offLabel="Disable">
<p:ajax listener="#{managedBean.changeStatusCity()}"/>
</p:selectBooleanButton>
<h:outputText value="Add neighborhood?"/>
<p:selectBooleanButton id="btAddNeighborhood" value="#{managedBean.addNeighborCity}" onLabel="Cancel" offLabel="Yes">
<p:ajax update=":addNeighbor" listener="#{managedBean.addNeighborCity()}"/>
</p:selectBooleanButton>
</p:panelGrid>
</h:form>
</p:column>
</p:row>
<p:row>
<p:column>
<h:form id="addNeighbor">
<p:panel header="Neighborhood" rendered="#{managedBean.addNeighborCity}">
<p:panelGrid columns="2">
<h:outputText value="Name: "/>
<p:inputText label="Name" value="#{managedBean.neighborhood.name}"/>
<h:outputText value="Status: "/>
<p:selectBooleanButton value="#{managedBean.neighborhood.status}" onLabel="Enable" offLabel="Disable" onIcon="ui-icon-check" offIcon="ui-icon-close">
<p:ajax listener="#{managedBean.changeStatusNeighbor()}"/>
</p:selectBooleanButton>
</p:panelGrid>
</p:panel>
</h:form>
<h:form id="formBt">
<p:commandButton id="bt" value="Add" actionListener="#{managedBean.saveNeighborCity()}" update=":addNeighbor, :city:btAddNeighborhood"/>
</h:form>
</p:column>
</p:row>
</p:panelGrid>`
And the manage bean
public void addNeighborCity(){
if(addNeighborCity){
neighborhood = new Neighborhood();
neighborhood .setStatus(true);
neighborhood .setStringStatus("Enable");
}else{
neighborhood = null;
}
}
public void changeStatusNeighbor() {
if (neighborhood .isStatus()) {
neighborhood .setStringStatus("Enable");
} else {
neighborhood .setStringStatus("Disable");
}
}
public void saveNeighborCity(){
city.getNeighborhoods().add(neighborhood );
neighborhood = null;
addNeighborCity = false;
}
All the input inside of the form that was rendered doesn't send the information to the manage bean and when I put the button that add the neighbor to the list of the city the button stop working and doesn't call the manage bean any more.
Does someone knows what I'm doing wrong or what is happening.
I'm using Primefaces3.5, GlassFish4.0 and JSF2.2
As you did not post the whole managed bean, I guess that you're using the default scope of the managed bean: #RequestScoped. In that case you should use #ViewScoped.
I solved the problem, I was using glassfish 4 and it forces the jsf2.2 even when you put the jsf2.1 in our project, then I changed to glassfish 3 and all work just fine, thanks for the answers, and I'm using #ScopeSession.
Is it possible to update view parameter without redirecting the page? For instance
I have a managed bean which checks if an ID exist
public void signIn(){
Client c = clientFacade.loginDetail(client.getID());
if (c != null) {
loggedIn = true;
}
else{
loggedIn = false;
}
}
and a view which renders just fine if the ID exist.
<h:panelGroup rendered="#{not applicationManager.loggedIn}">
<p:commandLink value="Sign In" onclick="loginDialog.show()" styleClass="login-link"></p:commandLink>
</h:panelGroup>
<h:panelGroup rendered="#{applicationManager.loggedIn}">
<p:menuButton value="#{applicationManager.client.firstname}" />
</h:panelGroup>
<p:dialog widgetVar="loginDialog" >
<h:panelGrid columns="2" cellpadding="5">
ID : <p:inputText value="#{applicationManager.client.id}" />
<p:commandButton value="submit" action="#{applicationManager.signIn()}" update=":loginForm" />
</h:panelGrid>
</p:dialog>
Is it possible to insert the code below at the top of the view and still have an update on the url?
<f:metadata>
<f:viewParam name="input" value="#{applicationManager.client.id}" />
<f:event listener="#{applicationManager.signIn()}" type="preRenderView"/>
</f:metadata>
I tried it, but it's not working, so I guess I might be missing something or doing something wrong.
I can not figure out why my rich:dataTable is not rendering. I am using JSF 2 and Richfaces 4. URL is http://localhost:8080/contacts-as7/me2.jsf?sitecode=0Z56, but it behaves the same without the sitecode parameter.
Here is the view
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j">
<h:head>
<title>contacts</title>
</h:head>
<f:metadata>
<f:viewParam name="sitecode" value="#{contactView.siteCode}" />
<f:event listener="#{contactView.retrieve056}" type="preRenderView"></f:event>
</f:metadata>
<h:form>
<h:messages />
<rich:panel rendered="#{not empty contactView.doors}">
<f:facet name="header">
<h:outputText value="Site Code #{contactView.doors.siteCode}" />
</f:facet>
<h:panelGrid columns="1">
<h:outputText
value="Report corrections to your DOORS administrator" />
<h:outputText id="nm1" value="#{contactView.doors.name}" />
<h:outputText id="pgr1" value="#{contactView.doors.pager}" />
<h:outputText id="adr1" value="#{contactView.doors.addr1}" />
<h:outputText id="adr2" value="#{contactView.doors.addr2}"
rendered="#{not empty contactView.doors.addr2}" />
<h:outputText id="csz"
value="#{contactView.doors.city}, #{contactView.doors.state} #{contactView.doors.zip}" />
</h:panelGrid>
</rich:panel>
<rich:dataTable value="#{contactView.doors.alternateList}" var="_xyz">
<h:panelGrid columns="1">
<h:outputText id="nm11" value="#{_xyz.name}" />
<h:outputText id="pgr11" value="#{_xyz.phone}" />
<h:outputText id="adr11" value="#{_xyz.pager}" />
<h:outputText id="adr21" value="#{_xyz.comment}" />
</h:panelGrid>
</rich:dataTable>
</h:form>
</html>
Here is my view bean
#Named
#ViewScoped
public class ContactView implements Serializable {
public ContactView() {
}
#EJB
ContactService contactService;
private String siteCode;
private Doors doors;
private AlternateContact alternateContact;
public String retrieve056() {
System.out.println("RETRIEVE");
this.doors = this.contactService.findDoors("0Z56");
System.out.println("doors_id is "+ doors.getDoorsId());
for ( AlternateContact alt : doors.getAlternateList() ){
System.out.println("alt name "+ alt.getName());
}
return "me2.jsf?sitecode=0Z56&faces-redirect=true";
}
}
And here is the output on the console -- the doors.getAlternateList() is definitely populated.
15:30:58,382 INFO [stdout] (http-localhost-127.0.0.1-8080-3) alt name Thomas Cahill
15:30:58,392 INFO [stdout] (http-localhost-127.0.0.1-8080-3) alt name Micahel Henry
And yet it doesn't show up on my view! I have been looking at this all day and am desparate. Any ideas? It was working at some point in the last few days, but I have no idea how I broke it as I was working on other things.
TDR
When using dataTable you should use rich:column or rich:columnGroup
Try using <rich:dataGrid> instead of <rich:dataTable>
Just look at rich:dataGrid...
Regards
Did you include the all the commons*.jar that goes with richfaces? Without that it won't render.
I have a composite component (collapsiblePanel). The component uses the "collapsible" bean to provide the toggle function. When I use the same component multiple times on a page, each instance of the component is bound to the same bean instance. How Can I achieve something like a component scoped bean?
collapsibleTemp.xhtml:
<cc:interface>
<cc:attribute name="model" required="true">
<cc:attribute name="collapsed" required="true" />
<cc:attribute name="toggle" required="true"
method-signature="java.lang.String f()" />
</cc:attribute>
<cc:actionSource name="toggle" />
<cc:facet name="header" />
<cc:facet name="body" />
</cc:interface>
<cc:implementation>
<h:panelGroup layout="block" styleClass="collapsiblePanel-header">
<h:commandButton id="toggle" action="#{cc.attrs.model.toggle}"
styleClass="collapsiblePanel-img"
image="#{cc.attrs.model.collapsed ? '/resources/images/plus.png' : '/resources/images/minus.png'}" />
<cc:renderFacet name="header" />
</h:panelGroup>
<h:panelGroup layout="block" rendered="#{!cc.attrs.model.collapsed}">
<cc:insertChildren />
<cc:renderFacet name="body"></cc:renderFacet>
</h:panelGroup>
<h:outputStylesheet library="css" name="components.css" />
</cc:implementation>
The backing bean:
#ManagedBean
#ViewScoped
public class Collapsible {
private boolean collapsed = false;
public boolean isCollapsed() {
return collapsed;
}
public void setCollapsed(boolean collapsed) {
this.collapsed = collapsed;
}
public String toggle() {
collapsed = !collapsed;
return null;
}
}
Using Page
<h:form id="someid">
<jl:collapsibletemp id="collapsiblePanel1" model="#{collapsible}">
<f:facet name="header">
<h3>
<h:outputText value="Collapsible information" />
</h3>
</f:facet>
<f:facet name="body">
<h:outputText value="do something....." />
</f:facet>
<p />
</jl:collapsibletemp>
<jl:collapsibletemp id="collapsiblePanel2" model="#{collapsible}">
<f:facet name="header">
<h3>
<h:outputText value="Collapsible information" />
</h3>
</f:facet>
<f:facet name="body">
<h:outputText value="do some tabbing" />
</f:facet>
<p />
</jl:collapsibletemp>
<jl:collapsibletemp id="collapsiblePanel3" model="#{collapsible}">
<f:facet name="header">
<h3>
<h:outputText value="Collapsible information" />
</h3>
</f:facet>
<f:facet name="body">
<h:outputText value="notice board" />
</f:facet>
<p />
</jl:collapsibletemp>
</h:form>
You can use the componentType attribute of the <cc:interface> to define a "backing component".
E.g.
<cc:interface componentType="collapsiblePanel">
...
</cc:interface>
<cc:implementation>
...
<h:commandButton action="#{cc.toggle}" ... />
...
<h:panelGroup rendered="#{!cc.collapsed}" ...>
...
</cc:implementation>
with just a com.example.components.CollapsiblePanel
#FacesComponent(value="collapsiblePanel") // To be specified in componentType attribute.
public class CollapsiblePanel extends UINamingContainer { // Important! Must extend UINamingContainer.
private boolean collapsed;
public void toggle() {
collapsed = !collapsed;
}
public boolean isCollapsed() {
collapsed;
}
}
However, when you want to have multiple of those components, then you should declare physically separate instances of them in the view. If this needs to happen dynamically, then you need to use <c:forEach> to generate physically separate instances of them instead of <ui:repeat> with a single component. Otherwise you have to map all collapsed states by the client ID inside a Map<String, Boolean>. See for an example and more background information also Getting same instance of `componentType` in composite component on every use