如何在JSF中动态地在表中添加行?

时间:2010-02-17 04:40:53

标签: jsf jsf-1.2 dynamic-forms

在我的应用程序中,我需要在单击按钮时添加一行,此按钮将在所有行中。需要帮助吗?

项目类

public class Item {
 public Item()
{

}
private String value;
public Item(String value) { this.value = value; }
public void setValue(String value) { this.value = value; }
public String getValue() { return value; }
}

管理Bean类

public class MyMB 
{
private List<Item> list;    

public void addItem() { // JSF action method
    list.add(new Item("Default"));
    Iterator<Item> iterator = list.iterator();
    while(iterator.hasNext())
    {
        Item item = (Item)iterator.next();
        System.out.println(item.getValue());
    }
    System.out.println();
    }
/**
 * @return the list
 */
public List<Item> getList() {
    if(list==null)
    {
        loadList();
    }
    return list;
}
private void loadList() {
    list = new ArrayList<Item>();
    list.add(new Item("Data"));
}

}

JSF代码

<h:form>
   <rich:dataTable value="#{myMB.list}" var="item" id="tabel">
    <h:column><h:inputText value="#{item.value}" /></h:column>
    <h:column><a4j:commandButton value="Add"  actionListener="#{myMB.addItem}" reRender="tabel"/></h:column>

    

2 个答案:

答案 0 :(得分:9)

您需要做的只是将value h:dataTable属性后面的数据模型添加一个空对象。

但同样的空行也需要在后续请求中保留。如果支持bean是请求作用域,则重新加载数据模型而不使用空行。当bean是会话范围时,这一切都应该有效。

此外,您的JSF代码中存在多个错误。缺少h:dataTable var属性,列内容需要位于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>

会话或视图范围 bean可能如下所示:

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;
    }
}

Item类当然应该有一个默认的无参数构造函数。通常这已经隐式可用,但如果您使用参数定义自己的构造函数,则它不再可用。您需要明确定义它,否则您将无法再执行Item item = new Item();

public class Item {

    private String value;

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

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

    // ...
}

如果您希望将bean保留在请求范围中,那么您需要保持新添加项的数量,以便bean可以在加载时保留相同的数量。

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());
        }
    }
}

您只需要将以下内容添加到JSF页面的<h:form>

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

有关以任何方式使用数据表的更多见解,您可能会发现本文非常有用:Using Datatables。它还包含一个WAR文件,在请求和会话范围内都包含大量示例。

答案 1 :(得分:2)

以此表为例:

<h:datatable value="#{myBean.list}" ...>
    ...
    <h:column>
       <h:commandButton value="Add a row" action="#{myBean.addRow}"/>
    </h:column>
</h:datatable>

方法 myBean.addRow 只会在列表中添加一个新元素:

public class MyBean {

    private List<SomeClass> list;

    ...

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

    public void addRow() {
        list.add(new SomeClass());
    }
}

当您点击该按钮时,方法 addRow 将在列表中添加一个新元素。该页面将刷新并显示带有新行的表。

编辑:

关于你的帖子版,有三件事:

第1点:您能否附上错误的堆栈跟踪?

第2点:您的方法addRow返回String,这是JSF用于导航的ID。由于此操作不涉及任何导航(即用户停留在同一页面上),只需返回null""

public String addRow() {
    list.add(new Item("new data"));
    return null;
}

第3点:我建议你的班级Item提供一个空的构造函数(除了你当前的构造函数):

public Item() {
}