【问题标题】:How to Dynamically add a row in a table in JSF?如何在 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>

【问题讨论】:

    标签: jsf jsf-1.2 dynamic-forms


    【解决方案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 我没有收到任何错误。但是添加的数据没有反映在屏幕上,当我迭代项目列表时,我可以在控制台中看到添加的数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 2011-04-11
    • 2016-08-27
    • 1970-01-01
    相关资源
    最近更新 更多