Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PrimeFaces commandButton in confirmDialog not calling backing bean

Tags:

jsf

primefaces

I have a PrimeFaces data table that displays a set of users with a commandLink to delete on each row. When the link is clicked, a confirmDialog appears with a "Yes" button that should call the "delete" method in the backing bean. Unfortunately, this method is not called and the dialog is just hidden. The parameter from the link is set because I saw it with the debugger.

Here is my 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">
<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><title>Manage users</title></h:head> 
<h:body>
<ui:composition template="../../template/commonLayout.xhtml">
    <ui:define name="content">
        <p:layoutUnit position="center">
            <h:form id="datatable">
                <p:tabView>
                    <p:tab title="Users">
                        <p:button value = "Add user" outcome="addUser.xhtml?faces-redirect=true"/>
                        <p:growl id="messages" showDetail="true"/>  
                        <p:dataTable id="usersTable" var="user" value="#{userMB.userList}" paginator="true" rows="25" 
                                     paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}">
                            <p:ajax event="rowEdit" listener="#{userMB.onEditUser}"  />
                            <p:column headerText="First name">
                                <h:outputText value="#{user.firstName}" />  
                            </p:column> 
                            <p:column headerText="Last name">
                                <h:outputText value="#{user.lastName}" />  
                            </p:column> 
                            <p:column headerText="E-mail">
                                <h:outputText value="#{user.email}" />  
                            </p:column>
                            <p:column headerText="Username">
                                <h:outputText value="#{user.username}"/>
                            </p:column> 
                            <p:column headerText="Hire date">
                                <h:outputText value="#{user.hireDate}">
                                    <f:convertDateTime type="date" pattern="dd.MM.yyyy"/>
                                </h:outputText>  
                            </p:column>  
                            <p:column headerText="Working hours">
                                <h:outputText value="#{user.workingHours}" />  
                            </p:column>
                            <p:column headerText="Vacation days">
                                <h:outputText value="#{user.vacationDays}"/>
                            </p:column>

                            <p:column>
                                <h:link outcome="addUser" value="Edit">
                                    <f:param name="userID" value="#{user.id}" />
                                </h:link>
                            </p:column>
                            <p:column>
                                <p:commandLink value="Delete" onclick="deleteConfirmDlg.show()">
                                    <f:setPropertyActionListener value="#{user}" target="#{userMB.currentUser}" />
                                </p:commandLink>
                            </p:column>                             
                        </p:dataTable>

                        <p:confirmDialog id="deleteConfirmDialog" message="Are you sure?" header="Delete user" severity="alert" widgetVar="deleteConfirmDlg" appendToBody="true">
                            <p:commandButton id="confirmDelete" value="Yes" oncomplete="deleteConfirmDlg.hide()" update="usersTable" actionListener="#{userMB.deleteUser}"/>
                            <p:commandButton id="declineDelete" value="No" onclick="deleteConfirmDlg.hide()" type="button"/>
                        </p:confirmDialog>
                    </p:tab>
                    <p:tab title="Teams">
                        <p:button value = "Add team" outcome="addTeam.xhtml?faces-redirect=true"/>
                        <p:dataTable var="team" value="#{userMB.teamList}" paginator="true" rows="25"
                            paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}">
                            <p:column headerText="Name">
                                <h:outputText value="#{team.name}" />  
                            </p:column>
                            <p:column headerText="Team leader">
                                <h:outputText value="#{team.teamLeader.displayName}" />  
                            </p:column>
                        </p:dataTable>
                    </p:tab>
                </p:tabView>
            </h:form>
    </p:layoutUnit>
    </ui:define>
</ui:composition>

Backing bean method:

public void deleteUser(ActionEvent event) {
    if (null != currentUser) {
        // check if userID is set and delete
        System.out.println("delete user with id " + currentUser.getId());
        userService.deleteUser(currentUser);
        currentUser = new User();
    }
}

I checked and I do not have nested forms as this is the most usual case for the backing bean not being called...

Here are my template files:

CommonLayout.xhtml

<?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:p="http://primefaces.org/ui">
 <h:head>
<h:outputStylesheet library="css" name="default.css"  />
</h:head>  
<h:body>
<p:layout fullPage="true">
<div id ="header">
<ui:insert name="header">
    <ui:include src="commonHeader.xhtml"></ui:include>
</ui:insert>
 </div>
 <div id="left-menu">
<ui:insert name="left-menu">
    <ui:include src="leftMenu.xhtml"></ui:include>
</ui:insert>
 </div>
 <div id ="content">
<ui:insert name="content">
    <ui:include src="commonContent.xhtml"></ui:include>
</ui:insert>
 </div>
</p:layout>
</h:body>
</html>

CommonHeader.xhtml:

<?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:p="http://primefaces.org/ui">
<h:head>
</h:head>  
<h:body>
    <ui:composition>
        <p:layoutUnit position="north" size="100">
            <h:outputText value="Welcome #{request.remoteUser}!"/> <br />
            <a href="#{request.contextPath}/j_spring_security_logout">Logout</a><br />
        </p:layoutUnit>
    </ui:composition>
</h:body>
</html>

CommonContent.xhtml:

<?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:p="http://primefaces.org/ui">
<h:head>
</h:head>  
<h:body>
    <ui:composition>
        <p:layoutUnit position="center">
                <ui:include src="../widgets/schedule.xhtml"/>
        </p:layoutUnit>
    </ui:composition>
</h:body>
</html>

LeftMenu.xhtml:

<?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:p="http://primefaces.org/ui">
<h:head>
</h:head>  
<h:body>
    <ui:composition>
        <p:layoutUnit position="west" size="200">
        <h:form>
            <p:menu width="100%" rendered="#{request.isUserInRole('ROLE_MANAGER')}">
                <p:submenu label="Management">
                    <p:menuitem value="Manage users" outcome="/pages/management/manageUsers.xhtml?faces-redirect=true"></p:menuitem>
                </p:submenu>
            </p:menu>
            </h:form>
    </p:layoutUnit>
    </ui:composition>
</h:body>
</html>

I am using PrimeFaces 3.4 and JSF 2.0

like image 348
AndaP Avatar asked Jan 11 '13 15:01

AndaP


1 Answers

The <p:confirmDialog ... appendToBody="true"> will cause the HTML representation of the confirm dialog to be relocated to end of HTML <body> element by JavaScript during DOM ready.

This however causes that the HTML representation of the confirm dialog is not inside any form anymore. So effectively no form is been submitted and no request parameters are been sent and so JSF won't be able to idenfity the action.

You need to give the confirm dialog its own <h:form>.

<p:confirmDialog ...>
    <h:form>
        ...
    </h:form>
</p:confirmDialog>

And to avoid confusion during maintenance (nesting forms is namely illegal), I also suggest to move that component to end of template, at least after the "outer" <h:form>.

like image 153
BalusC Avatar answered Oct 15 '22 11:10

BalusC