5

行のリストを表示する ah:datatable があり、各行のフィールドは入力フィールドです。

テーブルの前に「行を追加」ボタンを表示し、テーブルの各行に「行を削除」ボタンを表示します。

ベーキング Bean は viewScope であり、ボタンはバッキング Bean の Java リストに要素を追加/削除してから、同じビューに戻ります。

行を追加または削除するときに入力フィールドを検証しないように、ボタンの immediate 属性を「true」に設定しました。

すべて正常に動作しますが、入力フィールドの値がクリアされます。BeanがviewScopedであるため、ビューは値を保持していると思いました。

検証をトリガーせずに行を追加/削除し、ユーザーがフォームに既に入力した値を保持するにはどうすればよいですか?

私の見解:

<h:form>
    <h:commandButton value="Añadir Fila" immediate="true" action="#{tablaController.addRowAction}" />
    <h:dataTable value="#{tablaController.lista}" var="fila" cellpadding="0" cellspacing="0" border="1">
        <f:facet name="header">TABLA</f:facet>
        <h:column>
             <f:facet name="header"><h:outputLabel value="NOMBRE" /></f:facet>
             <h:inputText id="nom" value="#{fila.nombre}" />
             <h:message for="nom" class="msjError" />
        </h:column>
        <h:column>
            <f:facet name="header"></f:facet>
            <h:commandButton value="Quitar Fila" immediate="true" action="#{tablaController.removeRowAction(fila)}" />
        </h:column>
    </h:dataTable>
</h:form>

私のバッキングビーン:

@ManagedBean(name="tablaController")
@ViewScoped
public class TablaController {

private List<Fila> lista;
...
public TablaController() { }
...
@PostConstruct
public void init() {
    this.lista = new ArrayList<Fila>();
    for (int i=0; i<5; i++) {
        Fila fila = new Fila();
        fila.setNombre("");
        this.lista.add(i,fila);
    }
}
...
public String addRowAction () {
    Fila fila = new Fila();
    fila.setNombre("");
    this.lista.add(fila);
    return "";
}

public String removeRowAction (Fila f) {
    boolean exito = this.lista.remove(f);
    return "";
}
...
}

更新 --> 私の解決策:

誰かが興味を持っている場合は、ここに私の解決策を書きます。

問題は、immediate="true" を使用して検証をスキップすることですが、これにより update_model_values もスキップされるため、ユーザーがフォームに入力した値は、追加/削除ボタンをクリックしてページを再再定義した後に失われます。 .

「JSR-303 Bean 検証」を使用しているため、私の解決策は、f:validateBean を使用して検証をスキップし、それらを有効/無効にすることでした。クリックするボタンに応じて、検証を実行する場合は、Bean 検証を有効にし (たとえば、「送信」ボタンで)、それらをスキップする場合は、Bean 検証を無効にします (追加/削除のように)行ボタン)。しかし、とにかく update_model_values は常に実行されるため、値が失われることはありません。

ビューは次のとおりです。

<h:form>
    <f:validateBean disabled="#{!empty param['disableValidation']}">
        <h:commandButton value="Añadir Fila" action="#{tablaController.addRowAction}">
            <f:param name="disableValidation" value="true" />
        </h:commandButton>
        <h:dataTable value="#{tablaController.lista}" var="fila" cellpadding="0" cellspacing="0" border="1">
            <f:facet name="header">TABLA</f:facet>
            <h:column>
                <f:facet name="header"><h:outputLabel value="NOMBRE" /></f:facet>
                <h:inputText id="nom" value="#{fila.nombre}" />
                <h:message for="nom" class="msjError" />
            </h:column>
            <h:column>
                <f:facet name="header"></f:facet>
                <h:commandButton value="Quitar Fila" action="#{tablaController.removeRowAction(fila)}">
                    <f:param name="disableValidation" value="true" />
               </h:commandButton>
            </h:column>
        </h:dataTable>
        <h:commandButton value="Submit" action="#{tablaController.saveData}" />
    </f:validateBean>
</h:form>

バッキング Bean:

@ManagedBean(name="tablaController")
@ViewScoped
public class TablaController {

private List<Fila> lista;
...
public TablaController() { }
...
@PostConstruct
public void init() {
    this.lista = new ArrayList<Fila>();
    for (int i=0; i<5; i++) {
        Fila fila = new Fila();
        fila.setNombre("fila "+i);
        this.lista.add(i,fila);
    }
}
...
public String addRowAction () {
    Fila fila = new Fila();
    fila.setNombre("");
    this.lista.add(fila);
    return "";
}

public String removeRowAction (Fila f) {
    this.lista.remove(f);
    return "";
}
...
public String saveData () {
    ...
    //processes the valid data
    //for example, calls to a service method to store them in a database
    ...
    return "";
}
...
}
4

2 に答える 2

2

行を追加または削除するときに入力フィールドを検証しないように、ボタンの immediate 属性を「true」に設定しました。

immediate="true"仕事には間違ったツールです。検証を有効/無効にするのではなく、検証を優先するために使用する必要があります。あなたが自分自身に遭遇したように、違いはかなり大きいです。

条件付きで検証をトリガーしたい。たとえばrequired="true"、それは次のように簡単です

<h:inputText ... required="#{saveButtonPressed}" />

whereは、保存ボタンが押されたときに#{saveButtonPressed}評価されます。trueたとえば、そのクライアント ID がリクエスト パラメータ マップに存在する場合などです。

JSR 303 Bean 検証の場合、それは問題になります

<f:validateBean disabled="#{not saveButtonPressed}">
    <h:inputText ... />
</f:validateBean>

または、コマンドごとに制御できるOmniFacesを使用します。<o:validateBean>

<h:commandButton id="add" ...>
    <o:validateBean disabled="true" />
</h:commandButton>
于 2013-07-11T15:46:58.500 に答える
0

私はまったく同じ問題を抱えていました。つまり、データ テーブル (UIData) を更新するアクションまたは facelet の繰り返しに対して、immediate を使用することはできません。簡単な説明: UIData の入力が検証されない場合、送信された値は再表示のために保持されません。長い説明はここにあります: Mojarra の長い説明と関連するバグ

于 2013-07-11T04:23:31.390 に答える