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

发布于 2024-08-22 00:34:39 字数 1341 浏览 5 评论 0原文

在我的应用程序中,我需要单击按钮添加一行,并且该按钮将位于所有行中。需要帮助来做到这一点吗?

项目类

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>

In my application i need to add a row on a click of a button and this button will be in all the rows. Need help to do this?

Item Class

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

Manage Bean Class

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 code

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

箜明 2024-08-29 00:34:40

您所需要做的基本上只是将一个空对象添加到 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 可以在加载时保留相同的数量。

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:inputHidden binding="#{bean.count}" converter="javax.faces.Integer" />

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

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.

指尖凝香 2024-08-29 00:34:40

以此表为例:

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

Take this table as an example:

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

The method myBean.addRow will simply add a new element in your list:

public class MyBean {

    private List<SomeClass> list;

    ...

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

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

When you will click on the button, the method addRow will add a new element in the list. The page will refresh and display the table with a new row.

Edit:

Regarding your post edition, three things:

Point 1: Could you please attach the stacktrace of your error?

Point 2: Your method addRow return a String which is an ID used by JSF for the navigation. As this action does not involve any navigation (i.e. the user stay on the same page), simply return null or "":

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

Point 3: I suggest that your class Item provide an empty constructor (in addition of your current constructor):

public Item() {
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文