2015-07-31 31 views
8

Istnieją trzy tabele w bazie danych MySQL, category, sub_category i brand (producent) gdzie category jest dominującym tj spoczynku sub_category i brand. Mam nadzieję, że związek między menu może być bardziej przejrzysty w oparciu o relacje na stole.Resetowanie dziecko p: selectOneMenus wewnątrz AP: DataTable do pusta, kiedy wybrany jest oznaczony element w ich liście dominującej

Wszystkie trzy <p:selectOneMenu> S są umieszczone wewnątrz <p:dataTable> w trzech odpowiednich kolumnach zidentyfikowane przez <p:column>. Ignoruję wszystkie niedogodności dla zwięzłości.

row odpowiada JPA zarządzanego podmiotu będącego product w tym przypadku określone przez var="row" w <p:dataTable> związany.

To jest rzeczywisty znak zapytania: Po wybraniu elementu (pierwszy) o wartości null w categoryList (rodzica), jego dziecko wymienia subCategoryList i brandList reszta powinna być pusty.

Kategoria Lista: Lista

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

Podkategoria:

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

Marka (producent) Lista:

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

zarządzanego fasoli (leniwy model danych może być ignorowane w kontekście tego pytania):

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

W każdym przypadku wybrana wartość w dowolnym z tych menu nie jest dostarczana do odpowiedniego komponentu bean. Jest dostępny tylko w modelu wspieranym przez JPA (odpowiednio: value="#{row.category}", value="#{row.subCategory}" i value="#{row.brand}").

► Jak sygnalizować fasoli podkładową, że pierwszy element o wartości null (oznaczonego „Wybierz”) w menu nadrzędnego jest wybrany tak, aby jego dziecko wymienia resetowania opróżnić? Powinno to nastąpić w dowolny możliwy sposób, jeśli nie jest to wykonalne.

Używam finału PrimeFaces 5.2 (wydanie społecznościowe) i Mojarra 2.2.12.


to nie jest potrzebne, chyba że jest zerowy klucz obcy w tabeli podstawowej bazy konkretnie przy użyciu określonych ON DELETE SET NULL opcję pozwalającą dostawcy opcjonalnego rodzic w każdej (lub) odpowiedniego rzędu dziecięcej.

Odpowiedz

2

Do tego punktu należy się upewnić, że wywoływacz <f:selectItem> jest wywoływany z argumentem null. Innymi słowy, #{row.category} musi być null.Biorąc pod uwagę, że jesteś dla #{row.category} stosując model ALS pokazane w tej odpowiedzi, Populate p:selectOneMenu based on another p:selectOneMenu in each row of a p:dataTable, najprawdopodobniej, jak poniżej,

@Transient 
private Category category; 

public Category getCategory() { 
    return (category == null && subCategory != null) ? subCategory.getCategory() : category; 
} 

wtedy #{row.category} rzeczywiście nigdy być null gdy istnieje subCategory. Będzie tak w przypadku, gdy istniejący wpis danych zostanie przedstawiony w widoku.

Po prostu należy jawnie odrzucić wartość subCategory (i brand), gdy właściwość przejściowa category jest jawnie ustawiona na wartość null. To niedopatrzenie zostało w międzyczasie naprawione we wspomnianej odpowiedzi. Oto w jaki sposób nowa metoda setCategory() powinna wyglądać następująco:

public void setCategory(Category category) { 
    this.category = category; 

    if (category == null) { 
     subCategory = null; 
     brand = null; 
    } 
} 

ten sposób getCategory() będzie prawidłowo powrócić null i tym samym przeszedł w #{row.category} również.