将 p:dataTable 内的子 p:selectOneMenus 重置为空,当其父列表中的标记项目被选中时
Resetting child p:selectOneMenus inside a p:dataTable to empty, when a labelled item in their parent list is selected
MySQL数据库中有三个table,category
、sub_category
和brand
(制造商),其中category
是一个其余部分的父级,即 sub_category
和 brand
。希望根据table关系,菜单之间的关系可以更清晰
所有三个 <p:selectOneMenu>
都放置在 <p:dataTable>
中的三个相应列中,由 <p:column>
标识。为了简洁起见,我忽略了 <p:column>
、<p:cellEditor>
、<f:facet name="output">
、<f:facet name="input">
、<p:rowEditor>
和所有这些麻烦。
row
对应于一个 JPA 管理的实体,在这种情况下,它是 product
,由 <p:dataTable>
关联的 var="row"
指定。
This is the actual question mark : When an item (the first one) with a null
value in the categoryList
(parent) is selected ,它的子列表 subCategoryList
和 brandList
应该清空。
类别列表:
<p:selectOneMenu id="categoryList"
value="#{row.category}"
required="#{param['javax.faces.source'] ne component.clientId}">
<f:selectItem itemLabel="Select"
itemValue="#{null}"/>
<!-- When this item is selected, its children below should be reset to empty. -->
<f:selectItems var="category"
value="#{productManagedBean.categories}"
itemLabel="Select"
itemValue="#{category}"/>
<p:ajax update="subCategoryList brandList"/>
<!-- The listener functionality is left incomplete here. -->
</p:selectOneMenu>
子类别列表:
<p:selectOneMenu id="subCategoryList"
value="#{row.subCategory}">
<f:selectItem itemLabel="Select"
itemValue="#{null}"/>
<f:selectItems var="subCategory"
value="#{productManagedBean.getSubCategories(row.category)}"
itemLabel="#{subCategory.subCatName}"
itemValue="#{subCategory}"
rendered="true"/>
</p:selectOneMenu>
品牌(制造商)列表:
<p:selectOneMenu id="brandList"
value="#{row.brand}">
<f:selectItem itemLabel="Select"
itemValue="#{null}"/>
<f:selectItems var="brand"
value="#{productManagedBean.getBrands(row.category)}"
itemLabel="#{brand.brandName}"
itemValue="#{brand}"
rendered="true"/>
</p:selectOneMenu>
托管bean(惰性数据模型在这个问题的上下文中可以忽略):
@Named
@ViewScoped
public class ProductManagedBean extends LazyDataModel<Product> implements Serializable {
@Inject
private Service service;
// Associated with <p:selectOneMenu id="categoryList">.
private List<Category> categories; // Getter & setter.
// These are merely helper maps to reduce possible database calls.
private Map<Category, List<SubCategory>> subCategoriesByCategory;
private Map<Category, List<Brand>> brandByCategory;
public ProductManagedBean() {}
@PostConstruct
private void init() {
// This can be application scoped somewhere else as per business requirement.
categories = service.getCatgeoryList();
subCategoriesByCategory = new HashMap<Category, List<SubCategory>>();
brandByCategory = new HashMap<Category, List<Brand>>();
}
// This method populates <f:selectItems> associated with <p:selectOneMenu id="brandList">.
public List<SubCategory> getSubCategories(Category category) {
// category is never null here unless something is broken deliberately.
if (category == null) {
return null;
}
List<SubCategory> subCategories = subCategoriesByCategory.get(category);
if (subCategories == null) {
subCategories = service.findSubCategoriesByCategoryId(category.getCatId());
subCategoriesByCategory.put(category, subCategories);
}
return subCategories;
}
// This method populates <f:selectItems> associated with <p:selectOneMenu id="brandList">.
public List<Brand> getBrands(Category category) {
// category is never null here unless something is broken deliberately.
if (category == null) {
return null;
}
List<Brand> brands = brandByCategory.get(category);
if (brands == null) {
brands = service.findBrandsByCategoryId(category.getCatId());
brandByCategory.put(category, brands);
}
return brands;
}
}
在任何情况下,任何这些菜单中的选定值都不会提供给相应的支持 bean。它仅在 JPA 支持的模型中可用(分别为 value="#{row.category}"
、value="#{row.subCategory}"
和 value="#{row.brand}"
)。
► 如何向辅助 bean 发出信号,表明父菜单中具有 null
值(标记为 "Select")的第一项已被选中,以便将其子列表重置为空?如果这不可行,这应该以任何可行的方式发生。
我正在使用 PrimeFaces 5.2 final(社区版)和 Mojarra 2.2.12。
除非底层数据库中有空外键 table 专门使用供应商特定的 ON DELETE SET NULL
选项允许每个(或某些)可选父项,否则不需要这样做) 相应的子行。
至此,您需要确保使用 null
参数调用 <f:selectItem>
getter。换句话说,#{row.category}
必须是 null
。鉴于您 #{row.category}
使用此答案中显示的模型,Populate p:selectOneMenu based on another p:selectOneMenu in each row of a p:dataTable,很可能如下所示,
@Transient
private Category category;
public Category getCategory() {
return (category == null && subCategory != null) ? subCategory.getCategory() : category;
}
那么 #{row.category}
实际上永远不会是 null
当有 subCategory
时。当视图中显示现有数据条目时就是这种情况。
当瞬态 category
属性 显式设置为 null 时,您基本上需要显式清空 subCategory
(和 brand
)。同时,这种疏忽已在上述答案中得到解决。您的新 setCategory()
方法应该如下所示:
public void setCategory(Category category) {
this.category = category;
if (category == null) {
subCategory = null;
brand = null;
}
}
这样,getCategory()
将正确 return null
,因此传入的 #{row.category}
也会正确。
MySQL数据库中有三个table,category
、sub_category
和brand
(制造商),其中category
是一个其余部分的父级,即 sub_category
和 brand
。希望根据table关系,菜单之间的关系可以更清晰
所有三个 <p:selectOneMenu>
都放置在 <p:dataTable>
中的三个相应列中,由 <p:column>
标识。为了简洁起见,我忽略了 <p:column>
、<p:cellEditor>
、<f:facet name="output">
、<f:facet name="input">
、<p:rowEditor>
和所有这些麻烦。
row
对应于一个 JPA 管理的实体,在这种情况下,它是 product
,由 <p:dataTable>
关联的 var="row"
指定。
This is the actual question mark : When an item (the first one) with a null
value in the categoryList
(parent) is selected ,它的子列表 subCategoryList
和 brandList
应该清空。
类别列表:
<p:selectOneMenu id="categoryList"
value="#{row.category}"
required="#{param['javax.faces.source'] ne component.clientId}">
<f:selectItem itemLabel="Select"
itemValue="#{null}"/>
<!-- When this item is selected, its children below should be reset to empty. -->
<f:selectItems var="category"
value="#{productManagedBean.categories}"
itemLabel="Select"
itemValue="#{category}"/>
<p:ajax update="subCategoryList brandList"/>
<!-- The listener functionality is left incomplete here. -->
</p:selectOneMenu>
子类别列表:
<p:selectOneMenu id="subCategoryList"
value="#{row.subCategory}">
<f:selectItem itemLabel="Select"
itemValue="#{null}"/>
<f:selectItems var="subCategory"
value="#{productManagedBean.getSubCategories(row.category)}"
itemLabel="#{subCategory.subCatName}"
itemValue="#{subCategory}"
rendered="true"/>
</p:selectOneMenu>
品牌(制造商)列表:
<p:selectOneMenu id="brandList"
value="#{row.brand}">
<f:selectItem itemLabel="Select"
itemValue="#{null}"/>
<f:selectItems var="brand"
value="#{productManagedBean.getBrands(row.category)}"
itemLabel="#{brand.brandName}"
itemValue="#{brand}"
rendered="true"/>
</p:selectOneMenu>
托管bean(惰性数据模型在这个问题的上下文中可以忽略):
@Named
@ViewScoped
public class ProductManagedBean extends LazyDataModel<Product> implements Serializable {
@Inject
private Service service;
// Associated with <p:selectOneMenu id="categoryList">.
private List<Category> categories; // Getter & setter.
// These are merely helper maps to reduce possible database calls.
private Map<Category, List<SubCategory>> subCategoriesByCategory;
private Map<Category, List<Brand>> brandByCategory;
public ProductManagedBean() {}
@PostConstruct
private void init() {
// This can be application scoped somewhere else as per business requirement.
categories = service.getCatgeoryList();
subCategoriesByCategory = new HashMap<Category, List<SubCategory>>();
brandByCategory = new HashMap<Category, List<Brand>>();
}
// This method populates <f:selectItems> associated with <p:selectOneMenu id="brandList">.
public List<SubCategory> getSubCategories(Category category) {
// category is never null here unless something is broken deliberately.
if (category == null) {
return null;
}
List<SubCategory> subCategories = subCategoriesByCategory.get(category);
if (subCategories == null) {
subCategories = service.findSubCategoriesByCategoryId(category.getCatId());
subCategoriesByCategory.put(category, subCategories);
}
return subCategories;
}
// This method populates <f:selectItems> associated with <p:selectOneMenu id="brandList">.
public List<Brand> getBrands(Category category) {
// category is never null here unless something is broken deliberately.
if (category == null) {
return null;
}
List<Brand> brands = brandByCategory.get(category);
if (brands == null) {
brands = service.findBrandsByCategoryId(category.getCatId());
brandByCategory.put(category, brands);
}
return brands;
}
}
在任何情况下,任何这些菜单中的选定值都不会提供给相应的支持 bean。它仅在 JPA 支持的模型中可用(分别为 value="#{row.category}"
、value="#{row.subCategory}"
和 value="#{row.brand}"
)。
► 如何向辅助 bean 发出信号,表明父菜单中具有 null
值(标记为 "Select")的第一项已被选中,以便将其子列表重置为空?如果这不可行,这应该以任何可行的方式发生。
我正在使用 PrimeFaces 5.2 final(社区版)和 Mojarra 2.2.12。
除非底层数据库中有空外键 table 专门使用供应商特定的 ON DELETE SET NULL
选项允许每个(或某些)可选父项,否则不需要这样做) 相应的子行。
至此,您需要确保使用 null
参数调用 <f:selectItem>
getter。换句话说,#{row.category}
必须是 null
。鉴于您 #{row.category}
使用此答案中显示的模型,Populate p:selectOneMenu based on another p:selectOneMenu in each row of a p:dataTable,很可能如下所示,
@Transient
private Category category;
public Category getCategory() {
return (category == null && subCategory != null) ? subCategory.getCategory() : category;
}
那么 #{row.category}
实际上永远不会是 null
当有 subCategory
时。当视图中显示现有数据条目时就是这种情况。
当瞬态 category
属性 显式设置为 null 时,您基本上需要显式清空 subCategory
(和 brand
)。同时,这种疏忽已在上述答案中得到解决。您的新 setCategory()
方法应该如下所示:
public void setCategory(Category category) {
this.category = category;
if (category == null) {
subCategory = null;
brand = null;
}
}
这样,getCategory()
将正确 return null
,因此传入的 #{row.category}
也会正确。