There are three tables in MySQL database, category, sub_category and brand (manufacturer) where category is a parent of the rest i.e. sub_category and brand. I hope, the relationship between menus can be clearer based on the table relationships.
All of three <p:selectOneMenu>s are placed inside a <p:dataTable> in three respective columns as identified by <p:column>. I am ignoring <p:column>, <p:cellEditor>, <f:facet name="output">, <f:facet name="input">, <p:rowEditor> and all such nuisances for brevity.
row corresponds to a JPA managed entity which is product in this case as specified by var="row" in the <p:dataTable> associated.
This is the actual question mark : When an item (the first one) with a null value in the categoryList (parent) is selected, its child lists subCategoryList and brandList should be rest to empty.
Category List:
<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>
Subcategory List :
<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>
Brand (manufacturer) List :
<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>
The managed bean (lazy data model can be ignored in the context of this question) :
@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;
}
}
In any case, the selected value in any of these menus is not supplied to the corresponding backing bean. It is only available in the model backed by JPA (value="#{row.category}", value="#{row.subCategory}" and value="#{row.brand}" respectively).
► How to signal the backing bean that the first item with a nullvalue (labelled "Select") in the parent menu is selected so as to resetting its child lists to empty? This should happen in any feasible way, if this is not feasible.
I am using PrimeFaces 5.2 final (community release) and Mojarra 2.2.12.
This is not needed unless there is a null foreign key in the underlying database table specifically using the vendor specific ON DELETE SET NULL option allowing an optional parent in each (or some) corresponding child row.