Jsf 使用ajax包含XHTML文件时的表单行为

Jsf 使用ajax包含XHTML文件时的表单行为,jsf,jsf-2,Jsf,Jsf 2,我正在学习JSF,并尝试在本教程之后制作一个选项卡式窗格: 我已设法使tab开关工作。现在,我想包含一个在另一个XHTML文件中定义的表单,作为这个选项卡式窗格的选项卡,其中有一个dataTable,带有commandButton,用于删除所选行,名为clientes.XHTML。如果我直接导航到此页面,则“删除”按钮按预期工作。但当我将此页面包含在contentForm中时,它会按预期显示,但“删除”按钮不会执行预期的操作,它只刷新当前页面,但不会删除任何行 这就是我到目前为止所做的: we

我正在学习JSF,并尝试在本教程之后制作一个选项卡式窗格:

我已设法使tab开关工作。现在,我想包含一个在另一个XHTML文件中定义的表单,作为这个选项卡式窗格的选项卡,其中有一个
dataTable
,带有
commandButton
,用于删除所选行,名为
clientes.XHTML
。如果我直接导航到此页面,则“删除”按钮按预期工作。但当我将此页面包含在
contentForm
中时,它会按预期显示,但“删除”按钮不会执行预期的操作,它只刷新当前页面,但不会删除任何行

这就是我到目前为止所做的:

welcome.xhtml 和
clientsbeanjpa
sessionbean,以防万一:

clientsbeanjpa.java
编辑2 根据@Luiggi的建议,我测试了是否调用了
clientsmanagedbean#eliminar(cliente)
方法,我发现:

  • 如果默认情况下
    tabIndex
    属性设置为
    1
    ,则会呈现
    clientes.xhtml
    ,并按预期工作
  • 如果将
    tabIndex
    属性设置为另一个值,然后导航到选项卡1,则甚至不会调用
    eliminar(cliente)
包括
TabViewManagedBean
code以防万一

TabViewManagedBean.java
问题是您正在嵌套
,这是无效的HTML。这可以通过以下代码进行说明:

welcome.xhtml:


在clientes.xhtml中,您有:


以这种方式结束:


决定将
定义为不具有嵌套表单的位置。在我看来,您应该在尽可能狭窄的范围内定义
,在本例中,该范围仅在clientex.xhtml页面中(以及要包含的页面中)

更多信息:

  • (您的情景类似于已接受答案的案例2)

问题在于您正在嵌套
,这是无效的HTML。这可以通过以下代码进行说明:

welcome.xhtml:


在clientes.xhtml中,您有:


以这种方式结束:


决定将
定义为不具有嵌套表单的位置。在我看来,您应该在尽可能狭窄的范围内定义
,在本例中,该范围仅在clientex.xhtml页面中(以及要包含的页面中)

更多信息:

  • (您的情景类似于已接受答案的案例2)

问题在于您正在嵌套
,这是无效的HTML。这可以通过以下代码进行说明:

welcome.xhtml:


在clientes.xhtml中,您有:


以这种方式结束:


决定将
定义为不具有嵌套表单的位置。在我看来,您应该在尽可能狭窄的范围内定义
,在本例中,该范围仅在clientex.xhtml页面中(以及要包含的页面中)

更多信息:

  • (您的情景类似于已接受答案的案例2)

问题在于您正在嵌套
,这是无效的HTML。这可以通过以下代码进行说明:

welcome.xhtml:


在clientes.xhtml中,您有:


以这种方式结束:


决定将
定义为不具有嵌套表单的位置。在我看来,您应该在尽可能狭窄的范围内定义
,在本例中,该范围仅在clientex.xhtml页面中(以及要包含的页面中)

更多信息:

  • (您的情景类似于已接受答案的案例2)

谢谢Luiggi!我明白了这一点,我已经按照建议删除了
welcome.xhtml
中的
,并替换为
,以使用ajax重新渲染它。但是仍然是相同的行为:所有内容都正确呈现,但是
commandButton
不会删除任何内容。@dic19请通过编辑提供
clientsManagedBean
@dic19的定义,应该没有问题。您能否通过打印日志消息来验证该方法是否执行?谢谢Luiggi,我非常感谢您的努力。请看我的新编辑。我试图打印日志消息,但没有成功,除非默认情况下
tabIndex
设置为
1
。@dic19请在页面中的某个位置放置
,以检查是否存在转换/验证问题(一开始就很奇怪)。除此之外,我只能认为您的场景是我答案底部链接的案例7,因此我希望您测试删除操作的这种效果是否仅在第一次单击或几次单击时调用。遗憾的是,我手头没有一个完整的环境来测试这个。谢谢Luiggi!我明白了这一点,我已经按照建议删除了
welcome.xhtml
中的
,并替换为
,以使用ajax重新渲染它。但是仍然是相同的行为:所有内容都正确呈现,但是
commandButton
不会删除任何内容。@dic19请通过编辑提供
clientsManagedBean
@dic19的定义,应该没有问题。您能否通过打印日志消息来验证是否执行了该方法?谢谢Luiggi,
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                xmlns:h="http://xmlns.jcp.org/jsf/html"
                xmlns:f="http://xmlns.jcp.org/jsf/core"
                xmlns="http://www.w3.org/1999/xhtml"
                template="./templates/BasicTemplate.xhtml">

    <ui:define name="menu_bar">
        <h:form id="formMenu">            
            <ul id="menu-list"> 
                <li><h:commandLink value="Home">
                        <f:ajax event="click" render=":contentForm" listener="#{tabViewManagedBean.setTabIndex(0)}" />
                    </h:commandLink></li>
                <li><h:commandLink value="Clientes">
                        <f:ajax event="click" render=":contentForm" listener="#{tabViewManagedBean.setTabIndex(1)}" />
                    </h:commandLink></li>
                <li><h:commandLink value="Proveedores">
                        <f:ajax event="click" render=":contentForm" listener="#{tabViewManagedBean.setTabIndex(2)}" />
                    </h:commandLink></li>
            </ul>
        </h:form>
    </ui:define>

    <ui:define name="content">
        <h:form id="contentForm">
            <h:panelGroup layout="block" rendered="#{tabViewManagedBean.tabIndex == 0}">
                <h1>Hi there!</h1>
                <hr />
            </h:panelGroup>

            <h:panelGroup layout="block" rendered="#{tabViewManagedBean.tabIndex == 1}">
                <ui:include src="clientes.xhtml" />
            </h:panelGroup>

            <h:panelGroup layout="block" rendered="#{tabViewManagedBean.tabIndex == 2}">
                <ui:include src="proveedores.xhtml" />
            </h:panelGroup>
        </h:form>
    </ui:define>
</ui:composition>
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                xmlns:h="http://xmlns.jcp.org/jsf/html"
                xmlns:f="http://xmlns.jcp.org/jsf/core"
                xmlns="http://www.w3.org/1999/xhtml">
    <h:form>
        <h:dataTable id="dataTable" value="#{clientesManagedBean.listaClientes}" var="cliente">
            <h:column>
                <f:facet name="header">
                    <h:outputText value="Id" />
                </f:facet>
                <h:outputText value="#{cliente.idCliente}" />
            </h:column>

            <h:column>
                <f:facet name="header">
                    <h:outputText value="Fecha de ingreso" />
                </f:facet>
                <h:outputText value="#{cliente.fechaIngreso}">
                    <f:convertDateTime pattern="dd/MM/yyyy"/>
                </h:outputText>
            </h:column>

            <h:column>
                <f:facet name="header">
                    <h:outputText value="Nombre" />
                </f:facet>
                <h:outputText value="#{cliente.nombre}" />
            </h:column>

            <h:column>
                <f:facet name="header">
                    <h:outputText value="Domicilio" />
                </f:facet>
                <h:outputText value="#{cliente.domicilio}" />
            </h:column>

            <h:column>
                <f:facet name="header">
                    <h:outputText value="Teléfono" />
                </f:facet>
                <h:outputText value="#{cliente.telefono}" />
            </h:column>

            <h:column>
                <f:facet name="header" />
                <h:commandButton image="./resources/css/delete_16.png" action="#{clientesManagedBean.eliminarCliente(cliente)}"/>
            </h:column>

        </h:dataTable>
    </h:form>
</ui:composition>
import beans.interfaces.IClientesBeanLocal;
import domain.entities.ClienteJpa;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.view.ViewScoped;    

@ManagedBean
@ViewScoped
public class ClientesManagedBean {

    @EJB(beanName = "ClientesBeanJpa")
    private IClientesBeanLocal clientesBeanLocal;

    private List<ClienteJpa> listaClientes;
    private ClienteJpa cliente;

    @PostConstruct
    public void init() {
        listaClientes = new ArrayList<>();
        listaClientes.addAll(clientesBeanLocal.getTodos());
    }        

    public List<ClienteJpa> getListaClientes() {
        return listaClientes;
    }        

    public ClienteJpa getCliente() {
        return cliente;
    }

    public void eliminarCliente(ClienteJpa cliente) {            
        if(clientesBeanLocal.eliminar(cliente) == IClientesBeanLocal.EXITO) {
            listaClientes.remove(cliente);
        }
    }

}
import beans.interfaces.IClientesBeanLocal;
import domain.entities.ClienteJpa;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless(name = "ClientesBeanJpa")
public class ClientesBeanJpa implements IClientesBeanLocal {

    @PersistenceContext(unitName = "CursoJ2eePU")
    private EntityManager entityManager;

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public int eliminar(ClienteJpa cliente) {
        if(entityManager == null) {
            String error = "Error al inyectar EntityManager en la clase " + getClass().getCanonicalName();
            throw new ExceptionInInitializerError(error);
        } else {
            ClienteJpa clienteAEliminar = entityManager.getReference(ClienteJpa.class, cliente.getIdCliente());
            entityManager.remove(clienteAEliminar);
            return EXITO;
        }
    }
}
import javax.faces.bean.ManagedBean;
import javax.faces.view.ViewScoped;

@ManagedBean
@ViewScoped
public class TabViewManagedBean {

    private Integer tabIndex = 0;

    /*
     * If I set tabIndex to 1 then clientes.xhtml is rendered by default
     * and everithing works as expected.
     * But if I set this property to 0 and then navigate to tab 1 then it
     * behaves as described.
     */

    public TabViewManagedBean() {
        super();
    }

    public Integer getTabIndex() {
        return tabIndex;
    }

    public void setTabIndex(Integer tabIndex) {
        this.tabIndex = tabIndex;
    }

}