chardex
chardex

Reputation: 323

JSF 2.0 h:inputText inside ui:repeat

How I should change following example that after changes values in inputText not disappears after commandButton was submitted? I'm understanding why it happens, but I don't know how to fix it.

<h:form>
    <h:selectOneMenu valueChangeListener="#{foo.selectChanges}" onchange="submit()" >
        <f:selectItem itemValue="5" itemLabel="Five"/>
        <f:selectItem itemValue="10" itemLabel="Ten"/>
    </h:selectOneMenu>

    <ui:repeat value="#{foo.repeatItems}" var="item">
        <div>
            <h:inputText value="#{item.value}"/>
        </div>
    </ui:repeat>

    <h:commandButton value="test" action="#{foo.submit}">
    </h:commandButton>
</h:form>

And bean:

public class FooBean {

    private RepeatItem[] repeatItems;

    private String value = "5";

    public String getValue() {
        return value;
    }

    public void setValue(final String value) {
        this.value = value;
    }

    public void submit() {

    }

    public void selectChanges(ValueChangeEvent e) {
        value = (String) e.getNewValue();
    }

    public RepeatItem[] getRepeatItems() {
        repeatItems = new RepeatItem[Integer.parseInt(value)];

        for (int i = 0; i < Integer.parseInt(value); i++) {
            repeatItems[i] = new RepeatItem();
        }

        return repeatItems;
    }

    public void setRepeatItems(final RepeatItem[] repeatItems) {
        this.repeatItems = repeatItems;
    }

    public static class RepeatItem {

        private String value;

        public String getValue() {
            return value;
        }

        public void setValue(final String value) {
            this.value = value;
        }
    }
}

Upvotes: 3

Views: 6705

Answers (1)

BalusC
BalusC

Reputation: 1108632

You'd like to put the bean in the view scope to keep it alive in subsequent requests to the same view. You'd also like to prefill in the valueChangeListener method instead of the getter method since a getter method is called multiple times in JSF's lifecycle and is actually supposed to only return the data. You would also like to use f:ajax here to improve user experience by partial submits instead of submitting the whole page by Javascript's submit(). Here's a kickoff example:

XHTML:

<h:form>
    <h:selectOneMenu valueChangeListener="#{bean.prefill}" converter="javax.faces.Integer">
        <f:selectItem itemValue="0" itemLabel="Please select" />
        <f:selectItem itemValue="5" itemLabel="Five"/>
        <f:selectItem itemValue="10" itemLabel="Ten"/>
        <f:ajax event="change" render="items" />
    </h:selectOneMenu>
    <h:panelGroup id="items">
        <ui:repeat value="#{bean.items}" var="item">
            <div><h:inputText value="#{item.value}"/></div>
        </ui:repeat>
    </h:panelGroup>
    <h:commandButton value="submit" action="#{bean.submit}" />
    <h:messages />
</h:form>

Bean:

@ManagedBean
@ViewScoped
public class Bean {

    private List<Item> items;

    public void prefill(ValueChangeEvent event) {
        Integer count = (Integer) event.getNewValue();
        items = new ArrayList<Item>();
        while (count-- > 0) items.add(new Item());
    }

    public void submit() {
        System.out.println(items);
    }

    public List<Item> getItems() {
        return items;
    }    

}

Item:

public class Item {

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

}

See also:

Upvotes: 2

Related Questions