Question

I have a problem with <f:ajax> on a <h:inputText> inside <ui:repeat>. It successfully renders a <h:outputText> with the new value, but not a <h:inputText> (both are bound to the same property). However, if I change the <f:ajax> to render @form or @all, it works. But I obviously don't want/need to render the whole form.

I'm using Mojarra 2.2.4. Here's the index.xhtml

<h:form>
    <table>
        <ui:repeat var="line" value="#{myBean.lines}">
            <tr>
                <td>
                    <h:inputText value="#{line.number}">
                        <f:ajax event="change" execute="@this" render="desc1 desc2" listener="#{myBean.onChangeLineNumber(line)}"/>
                    </h:inputText>
                </td>
                <td>
                    <h:inputText id="desc1" value="#{line.desc}"/>
                    <h:outputText id="desc2" value="#{line.desc}"/>
                </td>
            </tr>
        </ui:repeat>
    </table>
</h:form>

And here's the relevant bit of the @ViewScoped bean:

public void onChangeLineNumber(Line line)
{
    line.setDesc("Some new text " + System.currentTimeMillis());
}

How is this caused and how can I solve it?

Was it helpful?

Solution

This is caused by a bug in state management of Mojarra's <ui:repeat> which is fixed as per issue 3215 as reported by my fellow Arjan Tijms (actually for a completely different problem, the fix just happens to solve exactly your problem as well). The fix is available in Mojarra 2.2.7. So upgrading to at least that version should do it.

Otherwise, your best bet is to replace it by a <h:dataTable>, the component which is designed for exactly the functional requirement of rendering a HTML table based on a collection. It also saves some HTML boilerplate.

<h:form>
    <h:dataTable value="#{myBean.lines}" var="line">
        <h:column>
            <h:inputText value="#{line.number}">
                <f:ajax render="desc1 desc2" listener="#{myBean.onChangeLineNumber(line)}"/>
            </h:inputText>
        </h:column>
        <h:column>
            <h:inputText id="desc1" value="#{line.desc}"/>
            <h:outputText id="desc2" value="#{line.desc}"/>
        </h:column>
    </h:dataTable>
</h:form>

(note that I removed event="change" and execute="@this" from the <f:ajax> as those are the defaults already, there's no need to repeat the defaults)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top