5

我有 ah:datatable 显示行列表,每行的字段都是输入字段。

我在表格前渲染了一个“添加行”按钮,并在表格的每一行上渲染了一个“删除行”按钮。

烘焙 bean 是 viewScoped,按钮从 backing bean 中的 java 列表中添加/删除元素,然后返回相同的视图。

我在按钮中将立即属性设置为“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

我在按钮中将即时属性设置为“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 重复的操作。简短说明:如果 UIData 中的输入未通过验证,则不会保留提交的值以供重新显示。长解释可以在这里找到:长解释Mojarra 中的相关错误

于 2013-07-11T04:23:31.390 回答