首页 文章

当选择父列表中的标记项时,将p:dataTable中的子p:selectOneMenus重置为空

提问于
浏览
8

MySQL数据库中有三个表, categorysub_categorybrand (制造商),其中 category 是其余的父级,即 sub_categorybrand . 我希望,菜单之间的关系可以根据表关系更清晰 .

所有三个_2596654都被放置在 <p:dataTable> 的三个相应列中,由 <p:column> 标识 . 为了简洁,我忽略了 <p:column><p:cellEditor><f:facet name="output"><f:facet name="input"><p:rowEditor> 以及所有这些麻烦 .

row对应于JPA管理实体,在这种情况下,该实体是由<p:dataTable>中的var =“row”指定的产品 .

This is the actual question mark : 当选择了 categoryList (父级)中具有 null 值的项目(第一个)时,其子列表 subCategoryListbrandList 应该为空 .

分类清单:

<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}" 和_2596673) .

►如何选择辅助bean,选择父菜单中具有 null 值(标记为"Select")的第一个项目,以便将其子列表重置为空?如果不可行,这应该以任何可行的方式发生 .

我正在使用PrimeFaces 5.2 final(社区发布)和Mojarra 2.2.12 .


除非基础数据库表中存在空外键,否则不需要这样做,具体使用供应商特定的ON DELETE SET NULL选项,允许每个(或某些)相应子行中包含可选父项 .

1 回答

  • 2

    至此,您需要确保使用 null 参数调用 <f:selectItem> getter . 换句话说, #{row.category} 必须是 null . 假设您使用的是 #{row.category} ,使用此答案中显示的模型als,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;
    }
    

    那么当 subCategory 时, #{row.category} 实际上永远不会 null . 当在视图中呈现现有数据条目时将是这种情况 .

    当瞬态 category 属性显式设置为null时,您基本上需要显式地使 subCategory (和 brand )无效 . 与此同时,这种疏忽已在上述答案中得到修正 . 以下是您的新 setCategory() 方法的外观:

    public void setCategory(Category category) {
        this.category = category;
    
        if (category == null) {
            subCategory = null;
            brand = null;
        }
    }
    

    这样, getCategory() 将正确返回 null ,从而也传入 #{row.category} .

相关问题