Search code examples
jsfmatrixdatatableprimefacesrichfaces

How to generate a matrix with JSF, Primefaces and Richfaces


I'm trying to make a 5x5 matrix in JSF 2.2 with Primefaces 6.2 and Richfaces 4.5.16.Final.

Quite similar to Generate Matrix Datatable with JSF Framework like Primefaces. The only difference is, I want the option to edit every cell (with a dropdown). I managed to make the 5x5 matrix with a dataTable, but this only gives me the option to edit the entire first row.

Problem here is that the dataTable manages the data per row, while I want to access the data per cell.

My current html is:

    <rich:dataTable value="#{testBean.data}" var="line" id="matrixTable" rowKeyVar="index" columnClasses="cellWidth">
                <f:facet name="header">
                    <rich:columnGroup>
                        <rich:column rowspan="2" style="width: 150px">
                            <h:outputText value="Ernst"/>
                        </rich:column>
                        <rich:column colspan="5">
                            <h:outputText value="Waarschijnlijkheid"/>
                        </rich:column>
                        <rich:column breakRowBefore="true" width="" style="width: 150px">
                            <h:outputText value="A: Onwaarschijnlijk"/>
                        </rich:column>
                        <rich:column style="width: 150px">
                            <h:outputText value="B: Mogelijk"/>
                        </rich:column>
                        <rich:column style="width: 150px">
                            <h:outputText value="C: Waarschijnlijk"/>
                        </rich:column>
                        <rich:column style="width: 150px">
                            <h:outputText value="D: Zeer waarschijnlijk"/>
                        </rich:column>
                        <rich:column style="width: 150px">
                            <h:outputText value="E: Zeker"/>
                        </rich:column>
                    </rich:columnGroup>
                </f:facet>
                <rich:column >
                    <h:outputText value="#{line.ROW_LABELS[index + 1]}"/>
                </rich:column>

                <rich:column style="background-color: #{line.inzetmogelijkhedenList[0].kleur}">
                    <div class="tooltip">

                        <c:choose>
                            <c:when test="#{testBean.readOnly}">
                                <h:outputText value="#{testBean.data[0].inzetmogelijkhedenList[0].code}"/>
                            </c:when>
                            <c:otherwise>
                                <h:selectOneMenu value="#{testBean.data[0].inzetmogelijkhedenList[0].code}" id="a1" label="a1" disabled="#{testBean.locked}">
                                    <f:selectItems value="#{testBean.inzetmogelijkhedenList}" var="b" itemLabel="#{b.omschrijving}"/>
                                </h:selectOneMenu>
                            </c:otherwise>
                        </c:choose>

                        <span class="tooltiptext">#{line.inzetmogelijkhedenList[0].omschrijving}</span>
                    </div>
                </rich:column>
                <rich:column style="background-color: #{line.inzetmogelijkhedenList[1].kleur}">
                    <div class="tooltip">
                        <h:outputText value="#{line.inzetmogelijkhedenList[1].code}"/>
                        <span class="tooltiptext">#{line.inzetmogelijkhedenList[1].omschrijving}</span>
                    </div>
                </rich:column>
                <rich:column style="background-color: #{line.inzetmogelijkhedenList[2].kleur}">
                    <div class="tooltip">
                        <h:outputText value="#{line.inzetmogelijkhedenList[2].code}"/>
                        <span class="tooltiptext">#{line.inzetmogelijkhedenList[2].omschrijving}</span>
                    </div>
                </rich:column>
                <rich:column style="background-color: #{line.inzetmogelijkhedenList[3].kleur}">
                    <div class="tooltip">
                        <h:outputText value="#{line.inzetmogelijkhedenList[3].code}"/>
                        <span class="tooltiptext">#{line.inzetmogelijkhedenList[3].omschrijving}</span>
                    </div>
                </rich:column>
                <rich:column style="background-color: #{line.inzetmogelijkhedenList[4].kleur}">
                    <div class="tooltip">
                        <h:outputText value="#{line.inzetmogelijkhedenList[4].code}"/>
                        <span class="tooltiptext">#{line.inzetmogelijkhedenList[4].omschrijving}</span>
                    </div>
                </rich:column>
            </rich:dataTable>

This is the backing bean:

@ViewScoped
@ManagedBean(name = "testBean")
public class testBean {

public List<Inzetmogelijkheden> getInzetmogelijkhedenList() {
    return referentieService.findAllActueel(Inzetmogelijkheden.class, getUser());
}

public List<RisicomatrixRegel> getData() {
    // actuele IZM uit DB halen
    List<Inzetmogelijkheden> actueleInzetmogelijkheden = getInzetmogelijkhedenList();

    RisicomatrixRegel line1 = new RisicomatrixRegel(Arrays.asList(actueleInzetmogelijkheden.get(0), actueleInzetmogelijkheden.get(0), actueleInzetmogelijkheden.get(0), actueleInzetmogelijkheden.get(0), actueleInzetmogelijkheden.get(1)));
    RisicomatrixRegel line2 = new RisicomatrixRegel(Arrays.asList(actueleInzetmogelijkheden.get(2), actueleInzetmogelijkheden.get(2), actueleInzetmogelijkheden.get(2), actueleInzetmogelijkheden.get(2), actueleInzetmogelijkheden.get(1)));
    RisicomatrixRegel line3 = new RisicomatrixRegel(Arrays.asList(actueleInzetmogelijkheden.get(2), actueleInzetmogelijkheden.get(2), actueleInzetmogelijkheden.get(2), actueleInzetmogelijkheden.get(3), actueleInzetmogelijkheden.get(1)));
    RisicomatrixRegel line4 = new RisicomatrixRegel(Arrays.asList(actueleInzetmogelijkheden.get(3), actueleInzetmogelijkheden.get(3), actueleInzetmogelijkheden.get(3), actueleInzetmogelijkheden.get(1), actueleInzetmogelijkheden.get(1)));
    RisicomatrixRegel line5 = new RisicomatrixRegel(Arrays.asList(actueleInzetmogelijkheden.get(1), actueleInzetmogelijkheden.get(1), actueleInzetmogelijkheden.get(1), actueleInzetmogelijkheden.get(1), actueleInzetmogelijkheden.get(1)));

    return new ArrayList<>(Arrays.asList(line1, line2, line3, line4, line5));
}

}

The result in reading mode: enter image description here

The result in editing mode: enter image description here

Any hints?


Solution

  • Is there any specific reason why you're using the rich prefix while using Primefaces?

    It seems you came from migrating legacy code that was attached to Richfaces instead, so, being legacy you use tag handlers instead of UI components, this is why you get an unexpected behaviour (only the first row being processed) in your Datatable.

    Replace the c:choose block with conditional renders instead.

    Also, you're accessing only the first line in your outputText and selectOneMenu components, replace them by line values.

    Also, and finally, NEVER NEVER use getter methods to build up your structures in the JSF managed beans! They could be called more than once while the view renders. Instead, build up your data in a method annotated with @PostConstruct or use f:viewAction:

    @ManagedBean
    @ViewScoped
    public class Bean {
    
        private List<RisicomatrixRegel> data;
    
        @PostConstruct
        public void init() {
            // actuele IZM uit DB halen
            List<Inzetmogelijkheden> actueleInzetmogelijkheden = referentieService.findAllActueel(Inzetmogelijkheden.class, getUser());
    
            RisicomatrixRegel line1 = new RisicomatrixRegel(Arrays.asList(actueleInzetmogelijkheden.get(0), 
                actueleInzetmogelijkheden.get(0), actueleInzetmogelijkheden.get(0), actueleInzetmogelijkheden.get(0), actueleInzetmogelijkheden.get(1)));
            RisicomatrixRegel line2 = new RisicomatrixRegel(Arrays.asList(actueleInzetmogelijkheden.get(2), 
                actueleInzetmogelijkheden.get(2), actueleInzetmogelijkheden.get(2), actueleInzetmogelijkheden.get(2), actueleInzetmogelijkheden.get(1)));
            RisicomatrixRegel line3 = new RisicomatrixRegel(Arrays.asList(actueleInzetmogelijkheden.get(2), 
                actueleInzetmogelijkheden.get(2), actueleInzetmogelijkheden.get(2), actueleInzetmogelijkheden.get(3), actueleInzetmogelijkheden.get(1)));
            RisicomatrixRegel line4 = new RisicomatrixRegel(Arrays.asList(actueleInzetmogelijkheden.get(3), 
                actueleInzetmogelijkheden.get(3), actueleInzetmogelijkheden.get(3), actueleInzetmogelijkheden.get(1), actueleInzetmogelijkheden.get(1)));
            RisicomatrixRegel line5 = new RisicomatrixRegel(Arrays.asList(actueleInzetmogelijkheden.get(1), 
                actueleInzetmogelijkheden.get(1), actueleInzetmogelijkheden.get(1), actueleInzetmogelijkheden.get(1), actueleInzetmogelijkheden.get(1)));
    
            data = Arrays.asList(line1, line2, line3, line4, line5);
        }
    
        public List<RisicomatrixRegel> getData() {
            return data;
        }
    
    }
    
    <h:outputText rendered="#{testBean.readOnly}" 
        value="#{line.inzetmogelijkhedenList[0].code}"/>
    <h:selectOneMenu rendered="#{!testBean.readOnly}" 
        value="#{line.inzetmogelijkhedenList[0].code}" id="a1" 
        label="a1" disabled="#{testBean.locked}">
        <f:selectItems value="#{testBean.inzetmogelijkhedenList}" var="b" itemLabel="#{b.omschrijving}"/>
    </h:selectOneMenu>
    

    See also: