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

Posted

技术标签:

【中文标题】如何在 JSF 的表中动态添加一行?【英文标题】:How to Dynamically add a row in a table in JSF? 【发布时间】:2011-01-17 17:06:48 【问题描述】:

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

物品类

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>

【问题讨论】:

【参考方案1】:

您需要做的基本上只是在h:dataTablevalue 属性后面的数据模型中添加一个空对象。

但同样的空行也需要在后续请求中保留。如果支持 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 在加载时可以保持相同的数量。 p>

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 页面的 &lt;h:form&gt;

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

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

【讨论】:

@BalusC :我对这种技术有疑问,当我按下按钮时,整个页面都会正确刷新,我们可以使用 Ajax 来完成这一切,以便这个过程是异步的。 是的,你可以。由于您还没有使用 JSF 2.0,因此您需要插入一些 3rd 方组件库。我可以向您推荐 JBoss RichFaces 的 Ajax4jsf 子组件。了解更多:jboss.org/file-access/default/members/jbossajax4jsf/freezone/… 通过您提供的链接,我尝试更改代码以支持 ajax。我收到一个错误,即 '#myMB.addItem' Method not found:....但我有Bean 类中的那个方法。我已经编辑了我的代码...请帮助 使用action 代替actionListener,或更改addItem 以采用ActionEvent 参数。【参考方案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 将在list 中添加一个新元素。页面将刷新并显示带有新行的表格。

编辑:

关于你的后期编辑,三件事:

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

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

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

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

public Item() 

【讨论】:

在 Bean 类的第 2 行中你提到了 SomeElement 并且在 getter 方法中你提到了 SomeClass...你能澄清一下 对不起,这只是一个错字。我已经编辑了我的帖子。当然,我使用的是同一种对象(因为您没有提供任何代码 sn-p,所以我对您的 JSF 页面和 bean 中的内容做了一些假设)。 您好,我已附上我的代码,但出现错误。您能帮忙。 @Hari 我已经编辑了我的帖子。如果我的建议不能解决您的问题,请提供您错误的堆栈跟踪... 感谢 romaintaz 我没有收到任何错误。但是添加的数据没有反映在屏幕上,当我迭代项目列表时,我可以在控制台中看到添加的数据。

以上是关于如何在 JSF 的表中动态添加一行?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JSF 中动态添加字段?

如何在 Ajax 请求期间在 JSF2 中动态添加组件

如何在 JSF 中动态添加 <h:inputtext>? [复制]

如何在反应中将多个值添加到动态表中?

如何在不使用按钮或 tbody 的情况下从动态生成的表中单击一行来获取 HTML 表中单元格的值

AJAX如何动态地将行添加到表中