代码之家  ›  专栏  ›  技术社区  ›  Alex Mi

JSF FacesMessage只显示一次,但应该在每次发生错误时显示

  •  0
  • Alex Mi  · 技术社区  · 6 年前

    我使用的是运行在WildFly 17(Ubuntu 18.04 TLS/或Windows 10)上的JSF 2.3(Mojarra 2.3.9.SP02)和PrimeFaces 7.0。 在我的行动方法中 weiterBid() 在backing bean(一个ViewScoped)中,我检查用户是否刚刚选中了复选框。如果没有,则组件中会显示红色错误消息 <p:panel id="errorMsgPanelId" (见下面的facelet),用户保持在同一页面上。每次用户单击“下一步”按钮时都会执行此检查。

    现在,我的理解是,即使当用户关闭错误消息面板时,每次他/她点击“下一步”按钮时,都会调用动作方法,并一次又一次地检查用户是否选中了复选框。如果未选中该复选框,则错误消息应再次显示在同一位置 <p:panel id="errorMsgPanelId"> 组件如前。 这真的是所谓的行为吗?如果是,那么我遇到了一个错误,错误消息只会在第一次点击“下一步”按钮时显示,一旦用户关闭显示它的面板,就再也不会显示了。

    github上的最小工作示例项目:

    https://github.com/alexmivonwien/pf.error.msg

    我的背豆:

        @Named("aveBidUnterlagenBean")
        @javax.faces.view.ViewScoped
        public class AveBidUnterlagenBean implements Serializable {
    
            private boolean confirmationDocumentsGiven;
    
            private FacesMessage errorMessageOnDocumentConfirmation;
    
            public boolean isConfirmationDocumentsGiven() {
                return confirmationDocumentsGiven;
            }
    
            public void setConfirmationDocumentsGiven(boolean confirmationDocumentsGiven) {
                this.confirmationDocumentsGiven = confirmationDocumentsGiven;
    
            }
    
            public String weiterBid() {
                if (!confirmationDocumentsGiven) {
                    String errorMessage = "Please confirm documents for the real estate";
    
                    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, errorMessage, null);
                    FacesContext.getCurrentInstance().addMessage(null, message);
                    this.errorMessageOnDocumentConfirmation = message;
                    return null;
                }
    
                return null;
            }   
    
            public FacesMessage getErrorMessageOnDocumentConfirmation() {
                return errorMessageOnDocumentConfirmation;
            }
    
            public void onCloseErrorMsgPanel(CloseEvent event) {
                this.errorMessageOnDocumentConfirmation = null;
            }
        }
    

    在不露面的我有组件

        <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:p="http://primefaces.org/ui">
    <h:head>
        <meta charset="UTF-8"/> 
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    </h:head>
            <h:outputStylesheet name="primeicons/primeicons.css" library="primefaces"/>
            <h:form id="persDatenForm">  
                    <p:panel id="errorMsgPanelId" styleClass="errorMsgPanel" closable="true" widgetVar="errorMsgPanel" rendered="#{aveBidUnterlagenBean.getErrorMessageOnDocumentConfirmation()!=null}">
                       <p:ajax event="close" listener="#{aveBidUnterlagenBean.onCloseErrorMsgPanel}" update="@parent" />
                       <h:outputText style="color:red;" value="#{aveBidUnterlagenBean.errorMessageOnDocumentConfirmation.detail}"/>
                       <p:commandLink outcome="#" style="background-color:white;" onclick="PF('errorMsgPanel').close()">
                            <i class="pi pi-times"></i>
                       </p:commandLink>
                    </p:panel>
                    <br/>
                    <p:outputLabel value="Documents overwiev"/>
                    <br/>
                    <br/>
                    <p:selectBooleanCheckbox value="#{aveBidUnterlagenBean.confirmationDocumentsGiven}" itemLabel="I confirm that I read the documents"/>
                    <br/>
                    <br/>
                    <p:commandButton  icon = "pi pi-check" value="Next" action="#{aveBidUnterlagenBean.weiterBid}" update="@form"/>
             </h:form>  
    </html>
    

    现在,我的问题是,如果我没有选中复选框,而是第一次单击“下一步”按钮,则会调用操作方法并显示错误消息。 如果我关闭错误消息面板,然后再次单击相同的“下一步”按钮,而没有选中复选框,则错误消息将不再显示。

    这是一个bug还是一个特性?我该如何克服它?

    感谢并致以亲切的问候:Alex

    0 回复  |  直到 6 年前
        1
  •  0
  •   theMahaloRecords    6 年前

    更新在操作后执行。相反,使用actionListener:

    <p:commandButton  icon = "pi pi-check" value="Next" actionListener="#{aveBidUnterlagenBean.weiterBid}" update="@form"/>
    

    update是在actionListener之后但在action之前调用的,我认为这是因为视图已经刷新了。因此,您的beans confirmationDocumentsGGiven为false,但它从未更新为正确的FacesContext。

    (我没有测试这个)

    好吧,我想问题是

    rendered="#{aveBidUnterlagenBean.getErrorMessageOnDocumentConfirmation()!=null}". 
    

    在onCloseErrorMsgPanel中,您将errorMessage设置为null。

    第一次访问:工作,设置错误消息,关闭对话框->错误消息为空,更新@parent->panel rendered=false,则调用该操作->然而,服务器端的所有值都是正确的

    第二次访问:update=“@form”或一般ajax更新将跳过所有rendered=false的组件

    怎么办?使用设置errormsg=/=PlaceHolder的操作。NotNull,然后调用update,加载面板(呈现为true,因为errormsg=/=null),然后使用actionlistener设置errormsg=actualValue。

    通过这种方式,面板应该被更新并包含在DOM中。

        2
  •  0
  •   Noah    6 年前

    这是变通办法,希望它能解决你的问题。
    <p:panel id="errorMsgPanelId" styleClass="errorMsgPanel" closable="true" widgetVar="errorMsgPanel">
    <p:outputPanel id="wrapper" rendered="#{aveBidUnterlagenBean.getErrorMessageOnDocumentConfirmation() != null}">
    <h:outputText style="color:red;" value="#{aveBidUnterlagenBean.errorMessageOnDocumentConfirmation.detail}"/>
    <p:commandLink style="background-color:white;" actionListener="#{aveBidUnterlagenBean.onCloseErrorMsgPanel}" update="@form" process="@this">
    <i class="pi pi-times"/>
    </p:commandLink>
    </p:outputPanel>
    </p:panel>

    并将backing bean方法更改为以下内容:
    public void onCloseErrorMsgPanel() { this.errorMessageOnDocumentConfirmation = null; }

    推荐文章