1

I have bilateral One to Many Relationship in a JSF + JPA application. I want to list out only filtered items from the list in the view. Doing it in the controller is difficult and is it possible to filted like below?

<p:selectOneListbox id="cmbField" value="#{investigationItemController.current}" >
     <f:selectItems value="#{investigationItemController.currentInvestigation.reportItems}" var="ri" itemLabel="#{ri.name}" itemValue="#{ri}" itemRendered="#{ri.retired ne true and ri.ixItemType eq 'Value'}" />        
</p:selectOneListbox>

As itemRendered is not an attribute, I tried this, but failed.

<p:selectOneListbox id="cmbField" value="#{investigationItemController.current}" >
    <ui:repeat value="#{investigationItemController.currentInvestigation.reportItems}" var="ri" >
        <h:panelGroup rendered="#{ri.retired ne true and ri.ixItemType eq 'Value'}" >
            <f:selectItem itemLabel="#{ri.name}" itemValue="#{ri}" />
        </h:panelGroup>
   </ui:repeat>
</p:selectOneListbox>

Owner Entity is as below.

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class InvestigationItem extends ReportItem implements Serializable {

    private static final long serialVersionUID = 1L;


    @OneToMany(mappedBy = "investigationItem", cascade= CascadeType.ALL)
    List<InvestigationItemValue> investigationItemValues;

    public List<InvestigationItemValue> getInvestigationItemValues() {
        return investigationItemValues;
    }

    public void setInvestigationItemValues(List<InvestigationItemValue> investigationItemValues) {
        this.investigationItemValues = investigationItemValues;
    }



}

The other entity is as follow

@Entity
public class InvestigationItemValue implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @ManyToOne
    private InvestigationItem investigationItem;
    private String name;

    //Getters and setters and some other fields


}

The important code set of the controller class is as follows

@ManagedBean
@SessionScoped
public final class InvestigationItemController implements Serializable {

    private static final long serialVersionUID = 1L;
    @EJB
    private InvestigationItemFacade ejbFacade;
    private InvestigationItem current;
    private Investigation currentInvestigation;

    // Other code goes here

}

How can I filter items when using f:selectItem or f:selectItems in JSF/Primefaces ?

(I will explain my real world situation why I desperately need this functionality.

I am developing a medical applications and terms are confusing. A test or an Investigation (like Full Blood Count or Urine Full Report) can have several properties. Test is represented as an Investigation Entity. A test comprised of one or more fields (like Haemoglobin, White Cell Count for FBC and Colour, Apperance for UFR). It is represented as InvestigationItem. A single InvestigationItem may have a list of possible values of which one is selected for in different occasions. They are identified as InvestigationItemValue. So one InvestigationItem has a list of InvestigationItemValue(s). But some of the InvestigationItemValues may be of string type while others are of numeric, for example. The user needs to select one InvestigationItemValue when designing a new investigation of one particular type. So filtering is needed in the view.)

Buddhika Ariyaratne
  • 2,339
  • 6
  • 51
  • 88
  • 2
    Why is it difficult to do this in the controller? That sounds to me like a usual task for the controller. Or are you just curious how you could do it in the view? – user1983983 Jul 12 '13 at 09:29
  • I have tried to explained in the edit of the question as much as I can. If we have a property like rendered in f:selectItems, I could have easily achieved this functionality. – Buddhika Ariyaratne Jul 12 '13 at 09:42
  • You're iterating a list named `reportItems`, then you need to filter it. Why should you do it using EL when you can create an auxiliar list before displaying it, based in `reportItems` and having the values filtered using java? – Aritz Jul 12 '13 at 09:49
  • The list of items is not comming from a List create in the within the controller itself. It is from a list in the entity with a bilateral OneToMany relationship. I can have many objects of InvestigationItem and each will have a different list of InvestigationItemValues. When persisting, I just need to persist the entity InvestigationItem and the relevant InvestigationItemValues will automatically saved. Or else, I have to create several lists of InvestigationItemValues to match different senarios of filtering mechanism. continued. ... – Buddhika Ariyaratne Jul 12 '13 at 10:25
  • Each time InvestigationItem is loaded, I have to manually fill every list. Saving also troublsome as I have to save all lists through a different session bean. All what I ask is something like I badly need an attribute like itemRendered for f:selectItems. Hope Primefaces will give something in future like p:selectItems with itemRendered property. – Buddhika Ariyaratne Jul 12 '13 at 10:28
  • Have you considered creating a wrapper class as a solution? – Emil Kaminski Jul 12 '13 at 10:44
  • I have no exposure to wrapper classes and I will refer it and try to apply it in this situation and post a comment hear. – Buddhika Ariyaratne Jul 12 '13 at 10:56
  • 1
    I am surprised that BalusC has not commented on this yet. Anyway, go to omnifaces google code project issue list, and add a feature request there. – Howard Jul 13 '13 at 03:49
  • Thanks. Added as a feature request. https://code.google.com/p/omnifaces/issues/detail?id=203&thanks=203&ts=1373693052 – Buddhika Ariyaratne Jul 13 '13 at 05:25
  • My bad, BalusC already responded to a similar topic, click [here](http://stackoverflow.com/a/6932217/933054) – Howard Jul 13 '13 at 15:19
  • 1
    also, see [this](http://stackoverflow.com/questions/10346618/update-of-a-conditionally-rendered-selectitem-not-working) – Howard Jul 13 '13 at 15:23
  • 1
    Read this one, [Disabled f:selectItem in p:selectOneRadio enable](http://forum.primefaces.org/viewtopic.php?f=3&t=10968). Someone added a renderer to their project to fix the issue. You can always add a renderer to your project which fixes. In my previous comment, that stackoverflow question, someone said that they were using MyFaces 2.1.7, and MyFaces 2.1.7 UISelectItem had a 'rendered' attribute. You can always add a feature request to Mojarra AND MyFaces JIRA/issue list, asking for them to add 'rendered' attribute to f:selectItem and f:selectItems. – Howard Jul 13 '13 at 15:27

1 Answers1

8

The PrimeFaces <p:selectOneListbox> actually hides the <select><option> and generates a <div><ul><li> which allows you much more CSS styling freedom.

You can just make use of itemDisabled attribute and then use CSS to set disabled items to display: none.

<p:selectOneListbox ...>
    <f:selectItems value="#{investigationItemController.currentInvestigation.reportItems}" 
        var="ri" itemLabel="#{ri.name}" itemValue="#{ri}"
        itemDisabled="#{not ri.retired and ri.ixItemType eq 'Value'}" />
</p:selectOneListbox>

with this CSS

.ui-selectlistbox-item.ui-state-disabled {
    display: none;
}

As to your failed attempt with <ui:repeat>; it failed because the <f:selectItem> is evaluated during view build time, not during view render time. However, the <ui:repeat> runs during view render time. During that moment the <f:selectItem> is nowhere available in the component tree. It's supposed to be attached to an UISelectOne/UISelectMany parent during view build time.

JSTL runs during view build time, like <f:selectItem>, so using JSTL <c:forEach> for the loop and <c:if> for the conditional building (not rendering!) should do it as well:

<p:selectOneListbox ...>
    <c:forEach items="#{investigationItemController.currentInvestigation.reportItems}" var="ri">
        <c:if test="#{not ri.retired and ri.ixItemType eq 'Value'}">
            <f:selectItem itemLabel="#{ri.name}" itemValue="#{ri}" />
        </c:if>
    </c:forEach>
</p:selectOneListbox>

You only need to take into account that this breaks view scoped beans when using a Mojarra version older than 2.1.18.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555