【问题标题】:Update and Process don't work properly in JSF 2.0 Primefaces 3.4更新和处理在 JSF 2.0 Primefaces 3.4 中无法正常工作
【发布时间】:2012-11-13 04:20:19
【问题描述】:

在此页面中,我将让用户通过单击复选框来显示密码。实际上应该隐藏两个输入(passwordconPassword)并显示另一个输入(passwordV)。所有这 3 个输入具有相同的值,并且需要在用户在这两种状态之间切换时保持它们的值:(具有两个可见的秘密字段或具有一个纯文本字段)

我把页面和bean代码放在​​这里:

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>

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

更新代码


我只是写了一个更简单的代码,以便您更容易理解我的问题:

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>

和豆:

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

如果我不将 process 属性添加到 &lt;p:ajax 标记,此代码可以隐藏两个字段并正确显示第三个字段。但是当用户在两种模式(2个秘密字段/1个纯文本字段)之间切换时,需要此属性以使这些字段保持其值

但它失败了!

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

第二次更新

我使用了重新显示并解决了空值问题,但输入仍然不会隐藏/显示,除非我将 updateprocess 设置为 @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>

【问题讨论】:

    标签: java jsf jsf-2 primefaces


    【解决方案1】:

    您的主要错误是您在客户端使用 CSS 切换输入字段的可见性,而不是在服务器端使用 JSF。所以 JSF 基本上永远不知道显示/隐藏哪一个。它所知道的只是显示了这两个字段。所以它将处理这两个字段。由于您已将这两个字段的值绑定到同一个属性,因此它始终会获得最后处理的字段的值。

    您需要在服务器端使用 JSF 来显示/隐藏输入字段。您可以使用为此提供的rendered 属性。

    rendered="#{testBean.visiblePassword}"
    

    【讨论】:

    • 我也尝试了服务器端隐藏,但这种情况下的问题是当我想第二次切换时,该值变为空。无论如何,我完全改变了我的 UI 设计,因为我找不到这个问题的真正解决方案。我什至创建了 3 个属性并将每个输入绑定到一个单独的属性!但仍然没有工作。所以我只留下了 2 个带有 2 个 outputText 的秘密字段,然后我显示/隐藏了那些 outputTexts。
    • 使用&lt;p:password redisplay="true"&gt; 重新显示提交的值。默认情况下,出于安全原因,它们不会重新显示。您不需要 3 个属性。一个就够了。
    • 请看看我更新的 Facelet。我用redisplay="true"
    【解决方案2】:

    问题是您将同一变量 entry.passwordEntry.password 绑定到 2 个或更多字段,因此在提交 &lt;h:form&gt; 时,这些字段中只有一个值将设置为 entry.passwordEntry.password,其他值将被丢弃。

    解决此问题的最佳方法是为您在表单上拥有/需要的每个字段设置不同的变量。通过查看您的代码,看起来可以通过在您的 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 代码:

    <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' : ''}"/>
    

    如果你想/需要在 2 或 3 个地方有相同的值,你必须考虑到绑定不应该在同一个&lt;h:form&gt;,否则你会遇到同样的问题。您可以同步使用纯 JavaScript 的变量值(毕竟,&lt;p:password&gt; 将是 &lt;input type="password"&gt;&lt;p:input&gt; 将是 &lt;input type="text"&gt;)或在服务器端执行操作时,即在您的 &lt;p:selectBooleanCheckbox&gt; 中选择一个值时应执行的侦听器。

    【讨论】:

    • 因此,如果用户填写密码字段(秘密字段)然后单击复选框,则 3ed 字段将为空!
    猜你喜欢
    • 2014-03-23
    • 1970-01-01
    • 2012-09-26
    • 2014-11-29
    • 2020-04-23
    • 2015-07-15
    • 1970-01-01
    • 2013-02-27
    • 2015-12-26
    相关资源
    最近更新 更多