简体   繁体   English

JSF数据表:添加和删除行清除行值

[英]JSF datatable: adding and removing rows clear rows values

I have ah:datatable showing a list of rows, and the fields of each row are input fields. 我有啊:数据表显示行列表,每行的字段是输入字段。

I render an "Add Row" button before the table, and a "Remove Row" button on each row of the table. 我在表格前面渲染一个“添加行”按钮,在表格的每一行上都有一个“删除行”按钮。

The baking bean is viewScoped, and the buttons add/remove elements from the java list in the backing bean, and then return to the same view. 烘焙bean是viewScoped,按钮添加/删除辅助bean中java列表中的元素,然后返回到同一视图。

I set the immediate attribute to "true" in the buttons in order to not validate the input fields when I add or remove a row. 我在按钮中将immediate属性设置为“true”,以便在添加或删除行时不验证输入字段。

Everything works ok but one thing: the values of the input fileds are cleared. 一切正常但只有一件事:输入文件的值被清除。 I thought that the view kept the values beacuse the bean is viewScoped. 我认为视图保持值,因为bean是viewScoped。

How can I achieve adding/removing rows without triggering validations and keeping the values that were already typed by the user in the form? 如何在不触发验证的情况下实现添加/删除行,并保留用户在表单中键入的值?

My view: 我的看法:

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

My backing 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("");
        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 "";
}
...
}

UPDATE --> MY SOLUTION: 更新 - >我的解决方案:

I write here my solution if someone is interested. 如果有人有兴趣,我在这里写我的解决方案。

The problem is that I use immediate="true" to skip validations, but this makes to skip the update_model_values too, so that the values entered by the user in the form are lost after clicking the add/remove buttons and re-redenring the page. 问题是我使用immediate =“true”来跳过验证,但这也会跳过update_model_values,因此在单击添加/删除按钮并重新重新登录页面后,用户在表单中输入的值将丢失。

As I use "JSR-303 bean validation", my solution was to skip validations using the f:validateBean to enable/disable them. 当我使用“JSR-303 bean验证”时,我的解决方案是使用f:validateBean跳过验证来启用/禁用它们。 Depending on the button I click, if I want the validations to execute, I enable the bean validation (for example in a "submit" button), and if I want to skip them, I disable bean validation (like in the add/remove row buttons). 根据我点击的按钮,如果我想要执行验证,我启用bean验证(例如在“提交”按钮),如果我想跳过它们,我禁用bean验证(如添加/删除行按钮)。 But anyway the update_model_values always executes, so the values are not lost. 但无论如何update_model_values总是执行,因此值不会丢失。

Here's the view: 这是观点:

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

The backing bean: 支持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 "";
}
...
}

I set the immediate attribute to "true" in the buttons in order to not validate the input fields when I add or remove a row. 我在按钮中将immediate属性设置为“true”,以便在添加或删除行时不验证输入字段。

immediate="true" is the wrong tool for the job. immediate="true"是错误的工具。 It should be used to prioritize validation, not to enable/disable validation. 它应该用于确定优先级 ,而不是启用/禁用验证。 The difference is rather huge as you encountered yourself. 你遇到自己时,差异很大。

You want to trigger validation conditionally. 您希望有条件地触发验证。 In case of eg required="true" that'd be as easy as 在例如required="true"情况下,就像那样容易

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

where #{saveButtonPressed} evaluates true when the save button is pressed. 其中#{saveButtonPressed}在按下保存按钮时评估为true Eg when its client ID is present in request parameter map. 例如,当其客户端ID存在于请求参数映射中时。

In case of JSR 303 bean validation, that'd be a matter of 在JSR 303 bean验证的情况下,这是一个问题

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

or with OmniFaces <o:validateBean> which allows controlling that on a per-command basis. 或者使用OmniFaces <o:validateBean> ,它允许在每个命令的基础上控制它。

<h:commandButton id="add" ...>
    <o:validateBean disabled="true" />
</h:commandButton>

I had exactly the same problem. 我有完全相同的问题。 In short, you can NOT use immediate for action that update data table(UIData) or facelet repeat. 简而言之,您不能立即使用更新数据表(UIData)或facelet重复的操作。 Short explanation:submitted values are not kept for re-display if inputs in UIData do not go through validation. 简短说明:如果UIData中的输入未通过验证,则不会保留提交的值以供重新显示。 Long explanation can be found here: long explanation and a related bug in Mojarra 这里可以找到很长的解释莫哈拉的 长解释相关的错误

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

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