【问题标题】:h:inputText inside ui:repeater displays wrong value after an ajax updateh:inputText inside ui:repeater 在 ajax 更新后显示错误的值
【发布时间】:2011-10-26 10:19:30
【问题描述】:

我有一个带有 ui:repeater 标记的 JSF 页面,它只显示字符串列表和一些用于将字符串添加到列表的控件。添加字符串时,我使用 ajax 更新转发器标记并立即显示新字符串,而无需刷新页面。这是我的页面的样子:

<h:body>
    <h:form>
        <p:inputText id="name" value="#{testController.newString}"/>
        <p:commandButton value="Add" actionListener="#{testController.addString}" update="strings" />
    </h:form>       

    <h:panelGroup id="strings">         
        <ui:repeat var="str" value="#{stringModel.strings}" varStatus="stringData">                                                                                                             
            <div>                                       
                <h:outputText value="#{str}" />
                <h:inputText value="#{str}" />
            </div>                                                                                  
        </ui:repeat>
    </h:panelGroup>                              

</h:body>

除了 inputText 组件外,一切正常。使用 Ajax 更新 ui-repeater 后,仍会显示上一个字符串中的文本。例如,假设最初我有一个包含 2 个字符串“val1”和“val2”的列表。我输入一个名为“val3”的新字符串并提交表单。列表在服务器端正确更新,转发器也更新,现在有 3 个元素。但是,虽然新添加的元素中的 h:outputText 将正确显示“val3”,但 inputText 将显示为“val2”作为值。所以我最终得到了这样的东西:

output tag     input tag
val1           val1
val2           val2
val3           val2 (???)

backing bean 非常简单: 视图范围的模型 bean

@Component
@Scope("view")
public class StringModel {

    private List<String> strings = Lists.newArrayList("Value 1");

    public List<String> getStrings() {
        return strings;
    }

    public void setStrings(List<String> strings) {
        this.strings = strings;
    }   
}

还有一个请求范围的控制器 bean:

@Component
@Scope("request")
public class TestController {

    private String newString;
    @Autowired private StringModel model;

    public void addString() {
        model.getStrings().add(newString);
    }

    public String getNewString() {
        return newString;
    }

    public void setNewString(String newString) {
        this.newString = newString;
    }   

}

我做了一些测试,这实际上对任何输入组件都以相同的方式工作,例如 textInput、textArea 等。任何帮助将不胜感激。

【问题讨论】:

  • 这毫无意义。您输出完全相同的 #{str} 两次。怎么可能改变?您可以尝试第三次打印 #{str} 看看它给出了什么吗?
  • 问题不在于我打印出来的次数,而在于 JSF 如何处理 ui:repeat 中的输入元素。我可以打印 10 次,所有输入组件都会有错误的值,而输出不会。
  • 我不敢相信您粘贴了正确的代码。我让你尝试打印第三个值,因为我认为你可能会在某个地方看到错误。显然你不是问题,而是这个异常错误......

标签: ajax jsf primefaces uirepeat


【解决方案1】:

我无法详细说明为什么它在更新后显示错误值(可能是 &lt;ui:repeat&gt; 的内部循环索引已损坏 - 尝试更新的 Mojarra 版本),但只是通过引用字符串项来自varStatus 的索引有效。它还可以立即解决将来当您将此列表放入表单时无法提交已编辑的字符串值的问题,因为String 类是不可变的并且没有设置器。

<ui:repeat value="#{stringModel.strings}" var="str" varStatus="loop">
    <div>
        <h:outputText value="#{str}" />
        <h:inputText value="#{stringModel.strings[loop.index]}" />
    </div>
</ui:repeat>

【讨论】:

  • 确实有效。感谢您指出这一点-我已经花了一天的时间,但从未想过要这样尝试。 (至于设置字符串,实际上我在那里有一个对象,我只是将其剥离为最简单的示例来说明问题)。
【解决方案2】:

ui:repeat 中的 EditableValueHolders 在当前版本的 JSF 规范中被破坏(按设计)。它不起作用,没有办法修复它。也许新版本将使 ui:repeat 成为支持保存其子项状态的适当组件。也许不会。

如果您将 ui:repeat 更改为 h:dataTable,则应该可以正常工作(如果没有,那么您的问题出在其他地方,我错了)。

坦率地说,除了使用来自其他一些库的中继器之外,没有其他解决方法 - 您应该在 Tomahawk、特立尼达和许多其他地方找到可用的中继器。 Primefaces,AFAIR,没有一个纯粹的中继器。

【讨论】:

  • @toto:在我看来这有点设计。围绕这个问题存在一定的不情愿,好像开发人员认为修复它违背了 JSF 架构(就像多字段验证的情况一样,我非常同意他们的观点)。转发器/uiinput 的问题在很长一段时间内众所周知(在 Mojarra 中打开了很多错误,有些是两年前的两个主要版本),但没有任何变化。
  • 嘿,我只想说这个答案真的很有帮助——它让我相信我没有疯。用 c:forEach 替换我的 a4j:repeat(它使用 ui:repeat)解决了我的问题。谢谢。
【解决方案3】:

我之前也遇到过同样的问题。我通过将 inputText 放入表单来解决它。我还复制了您的代码并将h:inputText 放入h:form 中,效果也很好。

<h:form>
    <ui:repeat value="#{stringModel.strings}" var="str" varStatus="loop">
        <div>
            <h:outputText value="#{str}" />
            <h:inputText value="#{str}" />
        </div>
    </ui:repeat>
</h:form>

【讨论】:

  • 表单展示会很好,但是表单提交不会很好(原因很简单,String 类是不可变的并且没有 setter 方法)。如何解决这个问题,请参阅我的答案。
猜你喜欢
  • 1970-01-01
  • 2011-07-25
  • 2019-03-15
  • 1970-01-01
  • 1970-01-01
  • 2012-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多