How to Dynamically add a row in a table in JSF?

All you need to do is basically indeed just adding an empty object to the datamodel behind the value attribute of h:dataTable.

But the same empty row needs to be preserved in the subsequent request as well. If the backing bean is request scoped, then the datamodel get reloaded without the empty row. This all should work when the bean is session scoped.

Further there are several errors in your JSF code. The h:dataTable var attribute is missing and the column content needs to be inside a h:column.

<h:form>
    <h:dataTable value="#{bean.list}" var="item">
        <h:column><h:inputText value="#{item.value}" /></h:column>
    </h:dataTable>
    <h:commandButton value="Add" action="#{bean.add}"/>
</h:form>

A session or view scoped bean can look like this:

public class Bean {
    private List<Item> list;

    public Bean() {
        list = new ArrayList<Item>();
    }

    public void add() {
        list.add(new Item());
    }

    public List<Item> getList() {
        return list;
    }
}

The Item class should of course have a default no-arg constructor. Normally this is already implicitly available, but if you define your own constructor with arguments, then it is not available anymore. You’ll need to explicitly define it, otherwise you cannot do Item item = new Item(); anymore.

public class Item {

    private String value;

    public Item() {
        // Keep default constructor alive.
    }

    public Item(String value) {
        this.value = value;
    }

    // ...
}

If you prefer to keep the bean in the request scope, then you’ll need to maintain the amount of newly added items, so that the bean can preserve the same amount on load.

public class Bean {
    private List<Item> list;
    private HtmlInputHidden count = new HtmlInputHidden();

    public Bean() {
        count.setValue(0);
    }

    public void add() {
        list.add(new Item());
    }

    public List<Item> getList() {
        if (list == null) loadList();
        return list;
    }

    public HtmlInputHidden getCount() {
        return count;
    }

    public void setCount(HtmlInputHidden count) {
        this.count = count;
    }

    private void loadList() {
        list = new ArrayList<Item>();

        // Preserve list with newly added items.
        for (int i = 0; i < (Integer) count.getValue(); i++) {
            list.add(new Item());
        }
    }
}

You’ll only need to add the following to the <h:form> of the JSF page:

<h:inputHidden binding="#{bean.count}" converter="javax.faces.Integer" />

For more insights about using datatables in any way you may find this article useful: Using Datatables. It also contains a WAR file with lot of examples in both request and session scope.

Leave a Comment