How to save h:inputText values of a h:dataTable? M

2020-03-08 06:15发布

问题:

I'm having trouble making a dataTable where each row has a inputText and a commandLink. When the link is clicked, only it's row's inputText's data is submitted.

Something like this?

<h:dataTable value="#{bean.items}" var="item">
    <h:column>
        <h:inputText value="#{bean.value}"/>
    </h:column>
    <h:column>
        <h:commandLink action="#{bean.save}" value="save">
            <f:setPropertyActionListener target="#{bean.item}" value="#{item}" />
        </h:commandLink>
    </h:column>
</h:dataTable>

Bean:

@RequestScoped
public class Bean {

    private Item item;
    private String value;

Right now, as it is, it's using the last row's inputText to fill the value. I wrapped another h:form, but it broke other things and I've learned that nested h:form is not the right way to do it hehe

What's the correct way to do this?

Thanks.

回答1:

You're binding the value of all HTML input elements to one and same bean property. This is of course not going to work if all those HTML input elements are inside the same form. All values are subsequently set on the very same property in the order as the inputs appeared in the form. That's why you end up with the last value. You'd like to move that form to inside the <h:column> (move; thus don't add/nest another one).

The usual approach, however, would be to just bind the input field to the iterated object.

<h:inputText value="#{item.value}"/>

An alternative, if you really need to have your form around the table, is to have a Map<K, V> as bean property where K represents the type of the unique identifier of the object behind #{item} and V represents the type of value. Let's assume that it's Long and String:

private Map<Long, String> transferredValues = new HashMap<Long, String>();

// +getter (no setter necessary)

with

<h:inputText ... value="#{bean.values[item.id]}" />

This way you can get it in the action method as follows:

String value = values.get(item.getId());

By the way, if you happen to target Servlet 3.0 containers which supports EL 2.2 (Tomcat 7, Glassfish 3, etc), then you can also just pass the #{req} as a method argument without the need for a <f:setPropertyActionListener>.

<h:commandLink ... action="#{bean.save(item)}" />

See also:

  • How and when should I load the model from database for h:dataTable
  • How can I pass selected row to commandLink inside dataTable?
  • How to dynamically add JSF components