1

Web アプリケーションで JSF 2.2 を使用していますが、f:validateRegex を使用して失敗するとビューに問題が発生します (immediate="true" を使用して同じページに再度移動しようとすると、ビューが正しくないため)バッキング Bean にオブジェクトの新しいインスタンスがある場合は更新されません)。私はリッチフェイスにバグがあると思っていたので(メインアプリケーションでjsfとリッチフェイスを使用しているため)、エラーの場所を特定するためにリッチフェイスを使用してリッチフェイスを使用せずに(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://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
    <h:head>
        <title>Mis pruebas con JSF</title>
    </h:head>
    <h:body>
        <h:form id="lista">
            <h:panelGrid id="principal">
                <h:dataTable value="#{indexBB.personas}" var="persona">
                    <h:column>
                        <f:facet name="header">Activo</f:facet>
                        <h:selectBooleanCheckbox value="#{persona.activo}"></h:selectBooleanCheckbox>
                    </h:column>
                    <h:column>
                        <f:facet name="header">Nombre</f:facet>
                        <h:outputText value="#{persona.nombre}"></h:outputText>
                    </h:column>
                    <h:column>
                        <f:facet name="header">Correo</f:facet>
                        <h:outputText value="#{persona.correo}"></h:outputText>
                    </h:column>
                </h:dataTable>
                <h:commandButton action="#{indexBB.crearPersona}" value="Crear Persona">
                </h:commandButton>
                <h:commandButton action="#{indexBB.activarBoton}" value="Activar Boton">
                </h:commandButton>
            </h:panelGrid>
        </h:form>
        <h:form id="crear">
            <h:panelGrid id="secundario" rendered="#{indexBB.crear}">
                <h:outputText value="Activo?">
                </h:outputText>
                <h:selectBooleanCheckbox label="Activo" value="#{indexBB.persona.activo}">
                </h:selectBooleanCheckbox>
                <br></br>
                <h:outputText value="Nombre"></h:outputText>
                <h:inputText label="Nombre" value="#{indexBB.persona.nombre}">
                </h:inputText>
                <br></br>
                <h:outputText value="Correo"></h:outputText>
                <h:inputText label="Nombre" value="#{indexBB.persona.correo}">
                    <f:validateRegex
                        pattern="[\w\.-]*[a-zA-Z0-9_]@[\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]" />
                </h:inputText>
                <br></br>
                <h:commandButton action="#{indexBB.guardarPersona}" value="Guardar Persona">
                </h:commandButton>
                <h:commandButton action="#{indexBB.cancelar}" value="Cancelar" immediate="true">
                </h:commandButton>
            </h:panelGrid>
        </h:form>
    </h:body>
</html>

豆:

package com.kanayet.martin.view.bb;

import com.kanayet.martin.model.entity.Persona;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Named;
import javax.faces.view.ViewScoped;

@Named(value = "indexBB")
@ViewScoped
public class indexBB implements Serializable {

    private Persona persona;
    private List<Persona> personas;
    private boolean crear;

    /**
     * Creates a new instance of indexBB
     */
    public indexBB() {
    }

    @PostConstruct
    public void onInit(){
        personas = new ArrayList<>();
        personas.add(new Persona("Martin", "martin@gmail.com", true));
        personas.add(new Persona("Andrea", "andrea@gmail.com", true));
        personas.add(new Persona("Camilo", "camilo@gmail.com", true));
        personas.add(new Persona("Felipe", "felipe@gmail.com", true));
        personas.add(new Persona("David", "david@gmail.com", true));
    }

    public void activarBoton() {
        persona = personas.get(0);
    }

    public void crearPersona(){
        crear = true;
        persona = new Persona();
    }

    public void guardarPersona(){
        personas.set(0, persona);
    }

    public void cancelar(){
    }

    public Persona getPersona() {
        return persona;
    }

    public void setPersona(Persona persona) {
        this.persona = persona;
    }

    public List<Persona> getPersonas() {
        return personas;
    }

    public void setPersonas(List<Persona> personas) {
        this.personas = personas;
    }

    public boolean isCrear() {
        return crear;
    }

    public void setCrear(boolean crear) {
        this.crear = crear;
    }

}

モデル: (オブジェクト)

package com.kanayet.martin.model.entity;   

public class Persona {

    private String nombre;
    private String correo;
    private Boolean activo;

    public Persona() {
    }

    public Persona(String nombre, String correo, Boolean activo) {
        this.nombre = nombre;
        this.correo = correo;
        this.activo = activo;
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public String getCorreo() {
        return correo;
    }

    public void setCorreo(String correo) {
        this.correo = correo;
    }

    public Boolean getActivo() {
        return activo;
    }

    public void setActivo(Boolean activo) {
        this.activo = activo;
    }

}

これがリッチフェイスを使用した私のテストコードです: (Beanとモデルは同じです)

意見:

<?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://xmlns.jcp.org/jsf/html"
      xmlns:a4j="http://richfaces.org/a4j"
      xmlns:rich="http://richfaces.org/rich"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head>
        <title>Mis pruebas con RichFaces</title>
    </h:head>
    <h:body>
        <h:form id="lista">
            <a4j:outputPanel id="principal">
                <rich:dataTable id="personas" value="#{indexBB.personas}"
                                var="persona" rows="50">
                    <rich:column>
                        <h:selectBooleanCheckbox label="Activo" value="#{persona.activo}">
                        </h:selectBooleanCheckbox>
                    </rich:column>
                    <rich:column>
                        <h:outputText value="#{persona.nombre}"></h:outputText>
                    </rich:column>
                    <rich:column>
                        <h:outputText value="#{persona.correo}"></h:outputText>
                    </rich:column>
                </rich:dataTable>
                <h:commandButton action="#{indexBB.crearPersona}" value="Crear Persona">
                </h:commandButton>
                <h:commandButton action="#{indexBB.activarBoton}" value="Activar Boton">
                </h:commandButton>
            </a4j:outputPanel>
        </h:form>
        <br></br>
        <h:form id="crear">
            <a4j:outputPanel id="secundario" rendered="#{indexBB.crear}">
                <h:outputText value="Activo?">
                </h:outputText>
                <h:selectBooleanCheckbox label="Activo" value="#{indexBB.persona.activo}">
                </h:selectBooleanCheckbox>
                <br></br>
                <h:outputText value="Nombre"></h:outputText>
                <h:inputText label="Nombre" value="#{indexBB.persona.nombre}">
                </h:inputText>
                <br></br>
                <h:outputText value="Correo"></h:outputText>
                <h:inputText label="Nombre" value="#{indexBB.persona.correo}">
                    <f:validateRegex
                        pattern="[\w\.-]*[a-zA-Z0-9_]@[\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]" />
                </h:inputText>
                <br></br>
                <h:commandButton action="#{indexBB.guardarPersona}" value="Guardar Persona">
                </h:commandButton>
                <h:commandButton action="#{indexBB.cancelar}" value="Cancelar" immediate="true">
                </h:commandButton>
            </a4j:outputPanel>
        </h:form>
    </h:body>
</html>

問題は、「Clear Persona」ボタンをクリックすると、たとえば「Nombre」: Felix と「Correo」: Felix と書き、「Guardar Persona」ボタンをクリックすると、有効な電子メールではないため f:validateRegex が失敗し、「最終ユーザーが電子メールで必要な値 (immediate="true") を知らないためです。もう一度、「Clear Persona」ボタンをクリックします (私の Bean の新しいオブジェクト)。jsf ページは更新されません。フォームは空である必要がありますが、そうではありません。フィールド「Nombre」には「Felix」値が残っていますが、私の Bean では属性に値のない新しい空のオブジェクトがあります。なぜでしょうか?

問題はリッチフェイスの有無に関係なく (問題はリッチフェイスである可能性があると思っていたが、そうではないため)、Bean に新しいオブジェクトがある場合に jsf ページが更新されない理由がわかりません。netbeans を使用しました確認するデバッグ ツールですが、正しいです。Bean に表示されるオブジェクトは異なります (サーバー側の新しい空のオブジェクト) が、私の JSF ページでは "Nombre" に "Felix" の値があり、なぜそれが起こるのか知りたいです。そして、この問題を解決する方法。

どうもありがとう。

4

1 に答える 1

1

問題は、JSF がモデルの 2 つの表現を保持していることです。Java オブジェクト IndexBB がありますが、UI の状態を追跡するコンポーネント ツリーもあります。

検証に失敗しても、コンポーネント ツリーには入力した値が含まれています。(これは、ユーザーが値を修正できる便利な機能です。) 以前はimmediate=true検証をスキップしていましたが、コンポーネント ツリーの値はリセットされません。

JSF 2.2 では、次を使用resetValuesしてコンポーネント ツリーの値をリセットできます。

<h:form id="crear">
    <h:panelGrid id="secundario" rendered="#{indexBB.crear}">
        <h:outputText value="Activo?">
        </h:outputText>
        <h:selectBooleanCheckbox label="Activo" value="#{indexBB.persona.activo}">
        </h:selectBooleanCheckbox>
        <br></br>
        <h:outputText value="Nombre"></h:outputText>
        <h:inputText id="nombreId" label="Nombre" value="#{indexBB.persona.nombre}">
        </h:inputText>
        <br></br>
        <h:outputText value="Correo"></h:outputText>
        <h:inputText id="correoId" label="Nombre" value="#{indexBB.persona.correo}">
            <f:validateRegex
                pattern="[\w\.-]*[a-zA-Z0-9_]@[\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]" />
        </h:inputText>
        <br></br>
        <h:commandButton  action="#{indexBB.guardarPersona}" value="Guardar Persona">
        </h:commandButton>
        <h:commandButton 
            action="#{indexBB.cancelar}" value="Cancelar">
            <f:ajax resetValues="true" render="crear:nombreId crear:correoId"/>
        </h:commandButton>
    </h:panelGrid>
</h:form>

変更点:

  1. 削除しimmediate=trueます。
  2. リセットする入力に ID を追加します。
  3. f:ajaxキャンセルボタンに追加します。
  4. resetValuesプロパティを追加しf:ajaxて ID をリストします (ID はコンマではなくスペースで区切ります)。

cancelarメソッドが実際にリセットされることを確認してくださいpersona。投稿したコードはこれを行いません。

エラー メッセージもリセットする場合はh:messages、フォームに を追加し、ID を指定して、それもリセットします。

こちらもご覧ください

于 2016-04-25T23:27:57.027 に答える