简体   繁体   English

更新和处理在JSF 2.0 Primefaces 3.4中无法正常工作

[英]Update and Process don't work properly in JSF 2.0 Primefaces 3.4

In this page I,m going to let the user to make the password visible by clicking a checkbox. 在此页面中,我将通过单击复选框让用户显示密码。 Actually two Inputs ( password , conPassword ) should hide and another input (passwordV) should be displayed. 实际上应该隐藏两个输入( passwordconPassword ),并显示另一个输入(passwordV)。 All these 3 inputs have the same value and needs to keep their values as user switches between these 2 states: (having two secret fields visible or having one plain text field) 所有这3个输入具有相同的值,并且需要将它们的值保持为用户在这两种状态之间切换:(具有两个可见的秘密字段或具有一个纯文本字段)

I put the page and bean code here: 我把页面和bean代码放在​​这里:

JSF Page: JSF页面:

<?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://java.sun.com/jsf/facelets"
                template="./templates/main_template.xhtml"
                xmlns:p="http://primefaces.org/ui"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns="http://www.w3.org/1999/xhtml">

  <ui:define name="subTitle">
    :: #{lbls.newEntry}   </ui:define>

  <ui:define name="content">
    <p:panel rendered="#{current.loggedIn}" header="#{lbls.newEntry}" >
      <h:form id="frmEntry">
        <h:panelGrid columns="3">

          <h:panelGroup>
            <h:outputLabel for="title" value="#{lbls.title}:"/>
            <p:focus for="title"/>
          </h:panelGroup>
          <p:inputText id="title" value="#{entry.passwordEntry.title}" maxlength="100" label="#{lbls.title}" required="true"/>
          <p:message for="title"/>

          <h:outputLabel for="description" value="#{lbls.description}:"/>
          <p:inputTextarea id="description" value="#{entry.passwordEntry.description}" maxlength="500" rows="3" cols="40" label="#{lbls.description}"/>
          <p:message for="description"/>

          <p:spacer height="10"/>
          <p:spacer height="10"/>
          <p:spacer height="10"/>

          <h:outputLabel for="username" value="#{lbls.username}:"/>
          <p:inputText id="username" value="#{entry.passwordEntry.username}" maxlength="100" label="#{lbls.username}"/>
          <p:message for="username"/>          

          <h:outputLabel for="password" id="lblPassword" value="#{lbls.password}:"  styleClass="#{entry.showPasswords ? 'none' : ''}" />  
          <p:password id="password" feedback="true" value="#{entry.passwordEntry.password}" match="conPassword" maxlength="100" 
                      label="#{lbls.password}" promptLabel="#{lbls.strengthPromp}" weakLabel="#{lbls.weakPassword}"  
                      goodLabel="#{lbls.goodPassword}" strongLabel="#{lbls.strongPassword}" styleClass="#{entry.showPasswords ? 'none' : ''}"
                      />
          <p:message id="msgPassword" for="password" class="#{entry.showPasswords ? 'none' : ''}"/>

          <h:outputLabel id="lblConPassword" for="conPassword" value="#{lbls.conPassword}:"
                         styleClass="#{entry.showPasswords ? 'none' : ''}"/>  
          <p:password id="conPassword" value="#{entry.passwordEntry.password}" label="#{lbls.conPassword}" maxlength="100"
                      styleClass="#{entry.showPasswords ? 'none' : ''}"/>
          <p:message id="msgConPassword" for="conPassword" class="display: #{!entry.showPasswords ? 'none' : ''}"/>

          <h:outputLabel id="lblPasswordV" for="passwordV" value="#{lbls.password}:" 
                         styleClass="#{!entry.showPasswords ? 'none' : ''}"/>  
          <p:inputText id="passwordV" value="#{entry.passwordEntry.password}"  maxlength="100" 
                       label="#{lbls.password}" 
                       styleClass="#{!entry.showPasswords ? 'none' : ''}"/>
          <p:message id="msgPasswordV" for="passwordV" 
                     class="#{!entry.showPasswords ? 'none' : ''}"/>

          <h:outputLabel for="showPasswords" value="#{lbls.showPasswords}:"/>
          <p:selectBooleanCheckbox id="showPasswords" label="#{lbls.showPasswords}" value="#{entry.showPasswords}">  
            <p:ajax process="password passwordV conPassword" update="password passwordV conPassword lblPassword lblPasswordV lblConPassword msgPassword msgConPassword msgPasswordV"/>
          </p:selectBooleanCheckbox>
          <h:outputText/>

          <p:spacer height="10"/>
          <p:spacer height="10"/>
          <p:spacer height="10"/>

          <h:outputLabel for="url" value="#{lbls.url}:"/>
          <p:inputText id="url" value="#{entry.passwordEntry.url}" maxlength="255" label="#{lbls.url}"/>
          <p:message for="url"/>

          <h:outputLabel for="ip" value="#{lbls.ip}:"/>
          <p:inputText id="ip" value="#{entry.passwordEntry.ip}" maxlength="255" label="#{lbls.ip}"/>
          <p:message for="ip"/>

          <p:spacer height="10"/>
          <p:spacer height="10"/>
          <p:spacer height="10"/>

          <h:outputLabel for="tags" value="#{lbls.tags}:"/>
          <p:autoComplete id="tags" value="#{entry.selectedTags}" 
                          completeMethod="#{entry.selectTag}" converter="PasswordEntry" multiple="true"
                          var="tag" itemLabel="#{tag.title}" itemValue="#{tag}" />  
          <p:message for="tags"/>

          <p:spacer height="10"/>
          <p:spacer height="10"/>
          <p:spacer height="10"/>

          <h:outputText/>
          <h:panelGroup layout="block" styleClass="right-align">
            <p:commandButton value="#{lbls.save}" actionListener="#{entry.save(event)}" 
                             update=":growl messages"/>
          </h:panelGroup>


          <f:facet name="footer">
            <p:messages id="messages"/>
          </f:facet>
        </h:panelGrid>
      </h:form>
    </p:panel>

    <ui:include src="/templates/not_logged_in.xhtml" rendered="!#{current.loggedIn}"/>   </ui:define>

</ui:composition>

and Bean: 和豆:

package package;


@ManagedBean(name = "entry")
@ViewScoped
public class PasswordEntryBean implements Serializable {

  //<editor-fold defaultstate="collapsed" desc="FIELDS">   
  private static final Logger logger = LogUtil.getLogger(PasswordEntryBean.class);
  private PasswordEntry passwordEntry;
  @ManagedProperty(value = "#{current}")
  private CurrentSessionBean current;
  private Database database;
  private List<PasswordTag> selectedTags = new ArrayList<PasswordTag>();
  private Set<PasswordTag> tags;
  private boolean showPasswords;
  //</editor-fold>  

  //<editor-fold defaultstate="collapsed" desc="CONSTRUCTORS">    
  public PasswordEntryBean() {
    passwordEntry = new PasswordEntry();
  }

  @PostConstruct
  public void init() {
  }
  //</editor-fold>

  //<editor-fold defaultstate="collapsed" desc="PROPERTIES">    
  public PasswordEntry getPasswordEntry() {
    return passwordEntry;
  }

  public Database getDatabase() {
    return database;
  }

  public boolean getShowPasswords() {
    return showPasswords;
  }

  public void setShowPasswords(boolean showPasswords) {
    this.showPasswords = showPasswords;
  }

  public void setDatabase(Database database) {
    this.database = database;
  }

  public Set<PasswordTag> getTags() {
    return tags;
  }

  public void setTags(Set<PasswordTag> tags) {
    this.tags = tags;
  }

  public List<PasswordTag> getSelectedTags() {
    return selectedTags;
  }

  public void setSelectedTags(List<PasswordTag> selectedTags) {
    this.selectedTags = selectedTags;
  }

  public void setPasswordEntry(PasswordEntry passwordEntry) {
    this.passwordEntry = passwordEntry;
  }

  public CurrentSessionBean getCurrent() {
    return current;
  }

  public void setCurrent(CurrentSessionBean current) {
    this.current = current;
  }
  //</editor-fold>
}

UPDATED CODE 更新的代码


I just wrote a simpler code in order to make it easier for you to understand my problem: 我刚写了一个更简单的代码,以便您更容易理解我的问题:

JSF: JSF:

<?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:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core">
  <h:head>
    <title>Facelet Title</title>
    <style type="text/css">
      .none {
        display: none;
      }
    </style>
  </h:head>
  <h:body>
    <h1>Register</h1>
    <h:form id="frmRegistration">
      <h:panelGrid columns="3">
        <h:outputLabel value="Username:" for="username"/>
        <p:inputText label="username" id="username" value="#{testBean.username}" required="true"/>
        <p:message for="username"/>

        <h:outputLabel value="Password:" id="lblPassword" for="password" styleClass="#{!testBean.visiblePassword ? '' : 'none'}"/>
        <p:password label="password" id="password" value="#{testBean.password}" 
                        styleClass="#{!testBean.visiblePassword ? '' : 'none'}"/>
        <p:message for="password" id="msgPassword" class="#{!testBean.visiblePassword ? '' : 'none'}"/>

        <h:outputLabel value="Confirm Password:" id="lblCpassword" for="cpassword" styleClass="#{!testBean.visiblePassword ? '' : 'none'}"/>
        <p:password label="confirm password" id="cpassword" value="#{testBean.password}" 
                        styleClass="#{!testBean.visiblePassword ? '' : 'none'}"/>
        <p:message for="cpassword" id="msgCpassword" class="#{!testBean.visiblePassword ? '' : 'none'}"/>

        <h:outputLabel value="Password:" id="lblVpassword" for="vpassword" styleClass="#{testBean.visiblePassword ? '' : 'none'}"/>
        <p:inputText label="password" id="vpassword" value="#{testBean.password}" 
                        styleClass="#{testBean.visiblePassword ? '' : 'none'}"/>
        <p:message for="vpassword" id="msgVpassword" class="#{testBean.visiblePassword ? '' : 'none'}"/>

        <h:outputLabel value="Show password"/>
        <p:selectBooleanButton value="#{testBean.visiblePassword}" 
                               onLabel="Yes" offLabel="No">
          <p:ajax update="messages password cpassword vpassword lblPassword lblCpassword lblVpassword msgPassword msgCpassword msgVpassword"
                   process="messages password cpassword vpassword" listener="#{testBean.addMessage}" />
        </p:selectBooleanButton>


        <f:facet name="footer">
          <p:commandButton actionListener="#{testBean.save(event)}" value="Save" update="messages"/>
          <p:messages id="messages"/>
        </f:facet>
      </h:panelGrid>
    </h:form>
  </h:body>
</html>

AND BEAN: 和豆:

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

@ManagedBean
@ViewScoped
public class TestBean {

  private String username;
  private String password;
  private boolean visiblePassword;

  public void addMessage() {
    String summary = visiblePassword ? "Checked" : "Unchecked";

    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(summary));
  }

  public TestBean() {
  }

  public void save(ActionEvent event) {
  }

  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  public boolean isVisiblePassword() {
    return visiblePassword;
  }

  public void setVisiblePassword(boolean visiblePassword) {
    this.visiblePassword = visiblePassword;
  }
}

This code can hide two fields and show the third field properly if I do not add process attribute to the <p:ajax tag. 如果我没有将进程属性添加到<p:ajax标记,则此代码可以隐藏两个字段并正确显示第三个字段。 But this attribute is needed in order to these fields keep their values when the user switches between two modes (2 secret fields / 1 plain text field) 但是,当用户在两种模式(2个秘密字段/ 1个纯文本字段)之间切换时,需要此属性才能使这些字段保持其值

But it fails! 但它失败了!

========================================================== ================================================== ========

SECOND UPDATE 第二次更新

I used redisplay and the problem of empty values solved but still the inputs don't hide/show unless I set the update and process to @form which is not good for my case. 我使用redisplay并解决了空值的问题,但仍然没有隐藏/显示输入,除非我将updateprocess设置为@form ,这对我的情况@form

<?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:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core">
  <h:head>
    <title>Facelet Title</title>
    <style type="text/css">
      .none {
        display: none;
      }
    </style>
  </h:head>
  <h:body>
    <h1>Register</h1>
    <h:form id="frmRegistration">
      <h:panelGrid columns="3">
        <h:outputLabel value="Username:" for="username"/>
        <p:inputText label="username" id="username" value="#{testBean.username}" required="true"/>
        <p:message for="username"/>

        <h:outputLabel value="Password:" id="lblPassword" for="password" rendered="#{!testBean.visiblePassword}"/>
        <p:password redisplay="true" label="password" id="password" value="#{testBean.password}" 
                        rendered="#{!testBean.visiblePassword}"/>
        <p:message for="password" id="msgPassword" rendered="#{!testBean.visiblePassword}"/>

        <h:outputLabel value="Confirm Password:" id="lblCpassword" for="cpassword" rendered="#{!testBean.visiblePassword}"/>
        <p:password redisplay="true" label="confirm password" id="cpassword" value="#{testBean.password}" 
                        rendered="#{!testBean.visiblePassword}"/>
        <p:message for="cpassword" id="msgCpassword" rendered="#{!testBean.visiblePassword}"/>

        <h:outputLabel value="Password:" id="lblVpassword" for="vpassword" rendered="#{testBean.visiblePassword}"/>
        <p:inputText label="password" id="vpassword" value="#{testBean.password}" 
                        rendered="#{testBean.visiblePassword}"/>
        <p:message for="vpassword" id="msgVpassword" rendered="#{testBean.visiblePassword}"/>

        <h:outputLabel value="Show password"/>
        <p:selectBooleanButton value="#{testBean.visiblePassword}" 
                               onLabel="Yes" offLabel="No">
          <p:ajax update="messages password cpassword vpassword lblPassword lblCpassword lblVpassword msgPassword msgCpassword msgVpassword"
                   process="password cpassword vpassword" listener="#{testBean.addMessage}" />
        </p:selectBooleanButton>


        <f:facet name="footer">
          <p:commandButton actionListener="#{testBean.save(event)}" value="Save" update="messages"/>
          <p:messages id="messages"/>
        </f:facet>
      </h:panelGrid>
    </h:form>
  </h:body>
</html>

The problem is that you're binding the same variable entry.passwordEntry.password to 2 or more fields, so when submitting the <h:form> only one of the values in those fields will be set to entry.passwordEntry.password , the other values will be discarded. 问题是您将相同的变量entry.passwordEntry.password绑定到2个或更多字段,因此在提交<h:form> ,这些字段中只有一个值将设置为entry.passwordEntry.password ,其他值将被丢弃。

The best way to solve this will be to have different variables for every field you have/need on the form. 解决此问题的最佳方法是为表单上您/需要的每个字段设置不同的变量。 By looking at your code, it looks like that can be achieved by having 3 PasswordEntry attributes in your bean: 通过查看代码,看起来可以通过在bean中使用3个PasswordEntry属性来实现:

@ManagedBean(name = "entry")
@ViewScoped
public class PasswordEntryBean implements Serializable {
    //other attributes...
    private PasswordEntry passwordEntry;
    private PasswordEntry passwordEntryV;
    private PasswordEntry conPasswordEntry;

    //<editor-fold defaultstate="collapsed" desc="CONSTRUCTORS">    
    public PasswordEntryBean() {
        passwordEntry = new PasswordEntry();
        passwordEntryV = new PasswordEntry();
        conPasswordEntry = new PasswordEntry();
    }

    //getters and setters...
}

JSF Code: JSF代码:

<p:password id="password" feedback="true" value="#{entry.passwordEntry.password}"
    match="conPassword" maxlength="100" label="#{lbls.password}"
    promptLabel="#{lbls.strengthPromp}" weakLabel="#{lbls.weakPassword}"
    goodLabel="#{lbls.goodPassword}" strongLabel="#{lbls.strongPassword}"
    styleClass="#{entry.showPasswords ? 'none' : ''}" />

<p:password id="conPassword" value="#{entry.conPasswordEntry.password}"
    label="#{lbls.conPassword}" maxlength="100"
    styleClass="#{entry.showPasswords ? 'none' : ''}"/>

<p:inputText id="passwordV" value="#{entry.passwordEntryV.password}"
    maxlength="100" label="#{lbls.password}"
    styleClass="#{!entry.showPasswords ? 'none' : ''}"/>

If you want/need to have the same value in 2 or 3 places, you have to take into account that the bindings should not be in the same <h:form> , otherwise you will have the same problem. 如果您希望/需要在2或3个位置具有相同的值,则必须考虑绑定不应位于相同的<h:form> ,否则您将遇到相同的问题。 You can synchronize the variable values using plain JavaScript (after all, the <p:password> will be <input type="password"> and <p:input> will be <input type="text"> ) or in the server side when executing an action ie the listener that should be executed when selecting a value in your <p:selectBooleanCheckbox> . 您可以使用纯JavaScript 同步变量值(毕竟, <p:password>将是<input type="password"><p:input>将是<input type="text"> )或在服务器中执行动作时的一面,即在<p:selectBooleanCheckbox>选择值时应执行的侦听器。

Your main mistake is that you're toggling visibility of the input fields using CSS in the client side, not using JSF in the server side. 您的主要错误是您在客户端使用CSS切换输入字段的可见性,而不是在服务器端使用JSF。 So JSF basically never knows which one is shown/hidden. 所以JSF基本上不知道哪一个被显示/隐藏。 All it knows is that both fields are shown. 它只知道两个字段都显示出来。 So it will process the both fields. 所以它将处理这两个领域。 As you've bound the value of the both fields to the one and same property, it will always end up getting the value of the last processed field. 当您将两个字段的值绑定到同一个属性时,它总是会获得最后处理字段的值。

You need to show/hide the input fields using JSF in the server side instead. 您需要在服务器端使用JSF显示/隐藏输入字段。 You can use the therefor provided rendered attribute. 您可以使用其提供的rendered属性。

rendered="#{testBean.visiblePassword}"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM