如何在JavaServerFaces2中维护对象列表
我有一个JSF2应用程序,它应该显示一个页面,其中必须在列表中添加一些os项。用户希望在一次保存操作中添加这些项目,设置它们的一些属性,并最终将它们全部保存在一起 此页应处理的域对象如下所示:如何在JavaServerFaces2中维护对象列表,java,jsf,jsf-2,Java,Jsf,Jsf 2,我有一个JSF2应用程序,它应该显示一个页面,其中必须在列表中添加一些os项。用户希望在一次保存操作中添加这些项目,设置它们的一些属性,并最终将它们全部保存在一起 此页应处理的域对象如下所示: public class Item { private long id; private String name; private Item previous; public Item() { } public Item(Item previousItem) {
public class Item {
private long id;
private String name;
private Item previous;
public Item() { }
public Item(Item previousItem) {
this.previous = previousItem;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Item getPrevious() {
return previous;
}
@ManagedBean
public class ItemBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<Item> items = new ArrayList<Item>();
public List<Item> getItems() {
if(items.size()==0) {
items.add(new Item()); // adding the first item
}
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
public void addItem(Item previousItem) {
Item newItem = new Item(previousItem);
items.add(newItem);
}
public void save() {
...
}
}
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<ui:composition template="/templates/layout.xhtml">
<ui:define name="content">
<h2>Items</h2>
<fieldset>
<legend>Items being added</legend>
<ui:repeat value="#{itemBean.items}" var="item">
<div>
<h:outputLabel value="Item" for="name" />
<h:inputHidden value="#{item.id}" />
<h:inputText id="name" value="#{item.name}" />
<h:commandLink action="#{itemBean.addItem(item)}">Add</h:commandLink>
</div>
</ui:repeat>
</fieldset>
<div class="options">
<h:commandButton action="#{itemBean.save}" value="Save"/>
<div class="clear border-bottom"></div>
</div>
</ui:define>
</ui:composition>
</body>
</html>
}
ItemBean类如下所示:
public class Item {
private long id;
private String name;
private Item previous;
public Item() { }
public Item(Item previousItem) {
this.previous = previousItem;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Item getPrevious() {
return previous;
}
@ManagedBean
public class ItemBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<Item> items = new ArrayList<Item>();
public List<Item> getItems() {
if(items.size()==0) {
items.add(new Item()); // adding the first item
}
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
public void addItem(Item previousItem) {
Item newItem = new Item(previousItem);
items.add(newItem);
}
public void save() {
...
}
}
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<ui:composition template="/templates/layout.xhtml">
<ui:define name="content">
<h2>Items</h2>
<fieldset>
<legend>Items being added</legend>
<ui:repeat value="#{itemBean.items}" var="item">
<div>
<h:outputLabel value="Item" for="name" />
<h:inputHidden value="#{item.id}" />
<h:inputText id="name" value="#{item.name}" />
<h:commandLink action="#{itemBean.addItem(item)}">Add</h:commandLink>
</div>
</ui:repeat>
</fieldset>
<div class="options">
<h:commandButton action="#{itemBean.save}" value="Save"/>
<div class="clear border-bottom"></div>
</div>
</ui:define>
</ui:composition>
</body>
</html>
请注意,为了添加新项,必须发送当前项以满足业务规则
问题是,我可以添加第二个项目而没有问题,但是当我单击第二个项目旁边的添加链接时,页面会重新显示一个项目,就像在页面中一样
不幸的是,即使在阅读了大量的文章、页面和一些书籍章节之后,我也看不出它还缺少什么
更新1
有人问我这个bean使用的范围是什么。它是默认范围(
@RequestScoped
)。为了可伸缩性,我试图避免使用@SessionScoped
,但在这种情况下,我不确定我是否有选择。任何有更多经验的人都可以给我一些提示?您需要使用ajax组件,比如:
<fieldset id="list">
<legend>Items being added</legend>
<ui:repeat value="#{itemBean.items}" var="item">
<div>
<h:outputLabel value="Item" for="name" />
<h:inputHidden value="#{item.id}" />
<h:inputText id="name" value="#{item.name}" />
<h:commandLink action="#{cargoBean.addItem(item)}">
<f:ajax render="list" />
Add
</h:commandLink>
</div>
</ui:repeat>
</fieldset>
正在添加的项目
添加
我在您的xhtml页面中没有看到类似以下的表单:
<h:form>
<ui:repeat>
<h:inputBlabla/>
</ui:repeat>
</h:form>
使用h:input字段时需要一个表单。您的
ManagedBean
的范围是什么
由于您没有发布任何持久性代码,我想
项列表只存在于Bean的整个生命周期中。这意味着,如果您的Bean是@ViewScoped
或@requestscope
,则在您提交表单后,您的项目将不再存在。感谢您的尝试,但当我添加
元素时,添加链接就消失了。我决定将其设置为
,链接再次可见,但最初的问题仍然存在。还有其他建议吗?谢谢你的回复!作用域是@RequestScoped
,这是托管bean的默认作用域。我正要问清楚这一点。我知道bean在视图构建并返回到浏览器后会被破坏,但是,在我维护单个实例的其他经验中,JSF足够聪明,可以将单个实例属性设置为它在页面中的状态,并且我希望集合也是如此。由于@SessionScoped
bean降低了应用程序的可伸缩性,我试图避免它。你怎么说?在这种情况下,使用@SessionScoped
是我唯一的选择吗?@AlexSC确实,@SessionScoped
将允许您在整个用户会话中保留您的项目。或者你可以把你的项目保存在某个地方(sessionMap,file,hibernate…),谢谢你的回复。这是一个合成视图。所使用的模板视图具有表单,因此这里您看到的只是整个视图的一部分。我可以确定最终/复合视图中有一个表单。