ui:repeat中的h:inputText的值未处理 [英] Values of h:inputText inside ui:repeat are not processed

查看:91
本文介绍了ui:repeat中的h:inputText的值未处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要处理这种形式(valueChangueListener在实际情况下无效).

这是背景豆:

public class TestBean extends PrivateBaseBean implements Serializable {
private List<String> strings;

@PostConstruct
public void init() {
    strings = new ArrayList<String>();
    strings.add("");
    strings.add("");
    strings.add("");
}

public void saveAction(ActionEvent event) {

    StringBuilder textToShowInMessage = new StringBuilder();
    for (String string : strings) {
        textToShowInMessage.append(string);
        textToShowInMessage.append("; ");
    }
    FacesMessage msg = new FacesMessage(super.getBundle().getString(
            textToShowInMessage.toString()), "");

    FacesContext.getCurrentInstance().addMessage(null, msg);
}

getters... setters...

视图:

....
<h:form>
<ui:repeat var="string" value="#{testBean.strings}">
    <h:inputText value="#{string}" />
    <br />
</ui:repeat>
<p:commandButton value="#{msg.save}"
actionListener="#{testBean.saveAction}" icon="ui-icon-disk"
        update="@form" />
</h:form>
...

在back bean字符串列表中处理表单时,始终为空白.

如何在没有任何值变化侦听器的情况下处理表单输入的内部迭代?

有一些屏幕截图:

相同的问题发生在action或actionListener上

解决方案

您的问题与PrimeFaces <p:commandButton>的行为无关,而是与使用<ui:repeat>标签时隐含的范围界定问题有关. /p>

首先,让我们偏离您的示例.基本上,您已经

<ui:repeat value="#{bean.strings}" var="s">
    <h:inputText value="#{s}"/>
</ui:repeat>

带有后勤List<String> strings.

罪魁祸首在这里: value="#{s}" . <ui:repeat>变量s导出的变量仅在其循环中可见,并且它未绑定到任何托管bean的属性,而仅绑定到局部变量.换句话说,s并不像人们期望的那样绑定/等于bean.strings[index],而且正如我们所看到的,它不知道其起源.因此,基本上,您是单方面的关系:Bean的值正确地打印在您的输入中,但是这种情况并没有发生.

解决方法

解决方法#1:包装类/模型对象

可以通过为类使用包装对象来克服这种情况.如果是字符串,则可能是简单的可变字符串",如下所示:

public class MString {
    private String string;//getter+setter+constructor
}

在这种情况下,迭代将按预期进行:

<ui:repeat value="#{bean.mstrings}" var="ms">
    <h:inputText value="#{ms.string}"/>
</ui:repeat>

带有后背List<MString> mstrings.

请注意,如果您有模型类(如User),并且将在<ui:repeat>中更改其属性,则该类本身实际上是包装器,因此可以适当地设置属性.

解决方法#2:链接属性访问

另一种解决方法是直接从<h:inputText>标记内访问集合的元素.这样,将通过访问Bean,然后进行收集,然后将属性设置为所需的索引来设置任何此类属性.太长了,但是就是这样.关于方式问题,<ui:repeat>提供了一个导出的当前迭代状态变量,varStatus,该变量将用于访问托管bean中的数组/集合.

在这种情况下,迭代也将按预期进行:

<ui:repeat value="#{bean.strings}" var="s" varStatus="status">
    <h:inputText value="#{bean.strings[status.index]}"/>
</ui:repeat>

具有普通支持List<String> strings.

I want to process this form (valueChangueListener is not valid in real case).

This is the back bean:

public class TestBean extends PrivateBaseBean implements Serializable {
private List<String> strings;

@PostConstruct
public void init() {
    strings = new ArrayList<String>();
    strings.add("");
    strings.add("");
    strings.add("");
}

public void saveAction(ActionEvent event) {

    StringBuilder textToShowInMessage = new StringBuilder();
    for (String string : strings) {
        textToShowInMessage.append(string);
        textToShowInMessage.append("; ");
    }
    FacesMessage msg = new FacesMessage(super.getBundle().getString(
            textToShowInMessage.toString()), "");

    FacesContext.getCurrentInstance().addMessage(null, msg);
}

getters... setters...

An the view:

....
<h:form>
<ui:repeat var="string" value="#{testBean.strings}">
    <h:inputText value="#{string}" />
    <br />
</ui:repeat>
<p:commandButton value="#{msg.save}"
actionListener="#{testBean.saveAction}" icon="ui-icon-disk"
        update="@form" />
</h:form>
...

When the form is processed in the back bean string list always is blank.

How to process form intput's inside iteration, without any value changue listener?

There are some screenshots:

The same problem occurs with action or actionListener on

解决方案

Your problem is not connected with PrimeFaces <p:commandButton>'s behaviour, but rather with a scoping problem that is implicilty created when using the <ui:repeat> tag.

First of all, let's depart from your example. Basically, you've got

<ui:repeat value="#{bean.strings}" var="s">
    <h:inputText value="#{s}"/>
</ui:repeat>

with the backing List<String> strings.

The culprit is here: value="#{s}". The exported by <ui:repeat> variable s is visible only within its loop and it is not bound to any managed bean's property, but instead only to a local variable. Put it differently, s is not bound/equal to bean.strings[index] as one would expect and has no knowledge, as we see, where it originated from. So basically, you're off with a unilateral relationship: value from the bean is printed in your input properly, but the reverse is not happening.

The workarounds

Workaround #1: wrapper classes / model objects

The situation can be overcome by using a wrapper object for your class. In case of a string it could be a 'simple mutable string', like below:

public class MString {
    private String string;//getter+setter+constructor
}

In this case the iteration will be working as predicted:

<ui:repeat value="#{bean.mstrings}" var="ms">
    <h:inputText value="#{ms.string}"/>
</ui:repeat>

with the backing List<MString> mstrings.

Note that if you have your model class, like User, and will change its properties within <ui:repeat> the class itself will be effectively a wrapper, so that the properties will be set appropriately.

Workaround #2: chained property access

Another workaround consists of accessing an element of your collection directly from within a <h:inputText> tag. This way, any such property will be set by accessing the bean, then collection, then setting the property at the desired index. Excessively long, but that's how it is. As to the how question, <ui:repeat> provides for an exported current iteration status variable, varStatus, that will be used to access the array/collection in the managed bean.

In this case the iteration will also be working as predicted:

<ui:repeat value="#{bean.strings}" var="s" varStatus="status">
    <h:inputText value="#{bean.strings[status.index]}"/>
</ui:repeat>

with the ordinary backing List<String> strings.

这篇关于ui:repeat中的h:inputText的值未处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆