【问题标题】:tabChange event on primefaces tabView doesn't set values in ManagedBeanprimefaces tabView 上的 tabChange 事件未在 ManagedBean 中设置值
【发布时间】:2014-10-14 13:41:05
【问题描述】:

我在使用 primefaces 5.0 和 jsf 2.2.5 时遇到问题。用一个 p:tabView 有两个选项卡共享同一个 ManagedBean 和同一个对象,事件 tabChange 没有按预期工作。当用户更改选项卡时,我想执行与单击按钮相同的验证,但事件并未刷新 bean 值,而是发布了值。我能够用这个简单的例子重现这个问题。 xhtml代码:

<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>

托管豆:

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);
}

}

发布的价值:

我试过 process="@this" process="@form" process="@all" immediate="true" 没有成功。我在这里错过了什么吗? 提前致谢。

重要更新:

在花了一些时间调试 primefaces 代码后,在 org.primefaces.component.api.UITabPanel 类中,我意识到 Primefaces 仅在其 process() 方法中处理子组件,如果它不是 ajax 请求的来源:

if(isRequestSource(context)) {
   return;
}

所以我删除了这段代码并重新编译了 primefaces,现在它可以正常工作了。我会公开这个问题,以防万一比我更有经验的人找到更好的解决方案。

【问题讨论】:

    标签: jsf jsf-2 primefaces


    【解决方案1】:

    试试这个。

    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>
    

    托管豆

    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;
        }
    
    }
    

    【讨论】:

    • 再次感谢您的回答。我明白你的意思,但想象一下你有多个选项卡的场景,如果用户当前在 tab3 中,然后用户点击 tab1,那么我必须验证 tab3 上的对象字段,如果没问题,转到选项卡1。这就是为什么我需要 tabChange 事件,我需要知道源选项卡和下一个选项卡。还有其他提示吗?
    【解决方案2】:

    primefaces 6.0 之后

    <p:ajax event="*" listener="*" skipChildren="false">
    

    skipChildren="false"

    帮助,并在侦听器的函数调用之前为托管 bean 设置值。

    【讨论】:

      猜你喜欢
      • 2014-10-07
      • 1970-01-01
      • 2013-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多