Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
968 views
in Technique[技术] by (71.8m points)

jsf - Values of h:inputText inside ui:repeat are not processed

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: Debug code

Form in browser

The same problem occurs with action or actionListener on See Question&Answers more detail:os


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...