Reputation: 362
I am facing a problem using primefaces 5.0 and jsf 2.2.5. Using a
p:tabView
with two tabs sharing the same ManagedBean and the same object the event tabChange
is not working as expected. When user change the tab I want to execute the same validation as if he had clicked the button, but the event is not refreshing the bean values, however the values are being posted. I was able to reproduce the problem with this simple example.
xhtml code:
<h:body>
<div class="well">
<h:form id="testeForm">
<p:tabView id="tView">
<p:ajax event="tabChange"
process="@this"
update="@form"
listener="#{testeBean.onTabChange}" />
<p:tab id="tab1" title="tab1">
<p:inputText id="teste1"
value="#{testeBean.evento.nome}" />
<p:commandButton id="savetab1"
process="tab1"
update="@form"
actionListener="#{testeBean.saveTab1}"
value="salvarTab1">
</p:commandButton>
</p:tab>
<p:tab id="tab2" title="tab2">
<p:inputText id="teste2"
value="#{testeBean.evento.descricao}" />
<p:commandButton id="savetab2"
process="tab2"
update="@form"
actionListener="#{testeBean.saveTab2}"
value="salvarTab2">
</p:commandButton>
</p:tab>
</p:tabView>
</h:form>
</div>
</h:body>
ManagedBean:
package com.example.bean;
@ViewScoped
@ManagedBean(name = "testeBean")
@Getter
@Setter
public class TesteBean {
private Evento evento;
@PostConstruct
public void init() {
evento = new Evento();
}
public void saveTab1() {
System.out.println(evento);
}
public void saveTab2() {
System.out.println(evento);
}
public void onTabChange(TabChangeEvent evt) throws LoundScreenException {
System.out.println(evt.getTab().getId());
System.out.println(evento);
}
}
The value being posted:
I tried process="@this" process="@form" process="@all" immediate="true"
without success. Am I missing something here?
Thanks in advance.
Important Update:
After spent some time debugging primefaces code, in the class org.primefaces.component.api.UITabPanel
I realize that Primefaces only processes child components in its process() methods if it is not the source of the ajax request:
if(isRequestSource(context)) {
return;
}
So I remove this piece of code and recompile primefaces and now it works fine. I'll let this question open, just in case of someone more experienced than me find a better solution.
Upvotes: 4
Views: 4759
Reputation: 601
After primefaces 6.0
<p:ajax event="*" listener="*" skipChildren="false">
skipChildren="false"
helps, and set value to managed beans before listener's function call.
Upvotes: 1
Reputation: 3164
Try this.
xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<!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">
<h:head>
<f:facet name="first">
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8" />
<meta name="viewport"
content="user-scalable=no,
width=device-width,
initial-scale=1.0,
maximum-scale=1.0"/>
</f:facet>
<title>page2</title>
</h:head>
<h:body>
<h:form id="testeForm">
<p:remoteCommand name="rc"
process="@this,tView:teste1,tView:teste2"
update="tView:teste1,tView:teste2"
actionListener="#{testeBean.execute}" />
<p:tabView id="tView" onTabChange="rc()">
<p:tab id="tab1" title="tab1">
<p:inputText id="teste1"
value="#{testeBean.evento.nome}" />
<p:commandButton id="savetab1"
process="tab1"
update="@form"
actionListener="#{testeBean.saveTab1}"
value="salvarTab1">
</p:commandButton>
</p:tab>
<p:tab id="tab2" title="tab2">
<p:inputText id="teste2"
value="#{testeBean.evento.descricao}" />
<p:commandButton id="savetab2"
process="tab2"
update="@form"
actionListener="#{testeBean.saveTab2}"
value="salvarTab2">
</p:commandButton>
</p:tab>
</p:tabView>
</h:form>
</h:body>
</html>
managedbean
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
/**
*
* @author Wittakarn
*/
@ViewScoped
@ManagedBean(name = "testeBean")
public class TesteBean implements Serializable{
private Evento evento;
public TesteBean(){
evento = new Evento();
}
@PostConstruct
public void init() {
}
public void saveTab1() {
System.out.println(evento.getNome());
System.out.println(evento.getDescricao());
}
public void saveTab2() {
System.out.println(evento.getNome());
System.out.println(evento.getDescricao());
}
public void execute() {
System.out.println(evento.getNome());
System.out.println(evento.getDescricao());
}
public Evento getEvento() {
return evento;
}
public void setEvento(Evento evento) {
this.evento = evento;
}
}
Upvotes: 2