TheCoder4eu / BootsFaces-OSP

BootsFaces - Open Source Project
Apache License 2.0
246 stars 102 forks source link

Add ability to add a row to the footer #881

Closed tg47 closed 5 years ago

tg47 commented 7 years ago

I have a table with a row of column totals that is meant to be the last row of the table. If I include this in the data table it will move around when the user sorts columns. Would it be possible to add the ability to define a footer row that will not be included in the table body. This functionality could be similar to how Bootsfaces now enables the definition of a header row.

ggam commented 7 years ago

Hi @tg47. So, just to verify I understood you correctly, you want to be able to specify a footer facet just like the header, right? Like

<b:dataTable value="#{tablePage.rows}" var="row">
    <b:dataTableColumn>
        <f:facet name="header">ID</f:facet>
        #{row.id}
        <f:facet name="header">#{tablePage.totalRows}</f:facet>
    </b:dataTableColumn>
</b:dataTable>

image

Yes I agree that feature must be supported.

chongma commented 7 years ago

this already works? I am using <b:dataTableColumn><f:facet name="footer">Something</f:facet></b:dataTableColumn>

tg47 commented 7 years ago

I define a table with column headings for employee, the 12 months of the year and then a total column.

I define the header using something like this:

<f:facet name="header">
  <tr>
     <th colspan="1"> Employee </th>
    <th colspan="1"> January </th> 
    <th colspan="1"> February </th> 
    <th colspan="1"> March </th> 
    <th colspan="1"> April </th>
    <th colspan="1"> May </th> 
    <th colspan="1"> June </th>
    <th colspan="1"> July </th> 
    <th colspan="1"> August </th>
    <th colspan="1"> September </th> 
    <th colspan="1"> October </th>
    <th colspan="1"> November </th> 
    <th colspan="1"> December </th>
    <th colspan="1"> Total </th> 
  </tr>

I would like to do a footer with the totals of these columns in the same way. For instance:

<f:facet name="footer">
  <tr>
     <th colspan="1"> Total</th>
    <th colspan="1"> <h:outputText value="#{backingBean.januaryTotal}"/> </th> 
    <th colspan="1"> <h:outputText value="#{backingBean.februaryTotal}"/> </th> 
    <th colspan="1"> <h:outputText value="#{backingBean.marchTotal}"/> </th> 
    <th colspan="1"> <h:outputText value="#{backingBean.aprilTotal}"/> </th>
    <th colspan="1"> <h:outputText value="#{backingBean.mayTotal}"/> </th> 
    <th colspan="1"> <h:outputText value="#{backingBean.juneTotal}"/> </th>
    <th colspan="1"> <h:outputText value="#{backingBean.julyTotal}"/> </th> 
    <th colspan="1"> <h:outputText value="#{backingBean.augustTotal}"/> </th>
    <th colspan="1"> <h:outputText value="#{backingBean.septemberTotal} "/> </th> 
    <th colspan="1"> <h:outputText value="#{backingBean.octoberTotal}"/> </th>
    <th colspan="1"> <h:outputText value="#{backingBean.novemberTotal}"/> </th> 
    <th colspan="1"> <h:outputText value="#{backingBean.decemberTotal}"/> </th>
    <th colspan="1"> <h:outputText value="#{backingBean.finalTotal}"/> </th> 
  </tr>

Chongma I tried to use your solution to establish the footers and it placed additional columns at the end of the table rows.

The program I have created is dynamic in that the users develop searches that can have different numbers of columns. The example I showed hard-coded the column names but actually in the program they are being formed by looping though a list of columns using a loop. I do the same for the table body.

I have been able to form the entire table. I just haven't been able to establish the footer row. I believe that if you set up the footer row to be established in the same way as the header row above this could accomplish this functionality.

This is my actual code from the xhtml file for creating the table.

<b:dataTable value="#{ctResultsBean.getCrossTabBody()}" widgetVar = "ctTable" id="crossTab" var="ctrow" scroll-horizontally="true" paginated="false"
        select="true" excel="true" pdf="true" columnVisibility="true">                                                   
        <f:facet name="header">                            
            <tr>
                <th colspan="1" rowspan="2"><h:outputText value="#{ctResultsBean.quickSearch.rowTitle}"/></th>
                <th colspan="#{ctResultsBean.getColumnTitleSpan()}" rowspan="1"><h:outputText value="#{ctResultsBean.quickSearch.columnTitle}"/></th>
                <th colspan="1" rowspan="2">Total</th>                                
            </tr>                               
            <tr>
                <c:forEach items="#{ctResultsBean.getColumnDisplayList()}" var="columnlabel">    
                    <th colspan="1"><h:outputText value="#{columnlabel}"/></th>
                </c:forEach>    
            </tr>                                                      
        </f:facet>                                
        <c:forEach items="#{ctResultsBean.crossTab.crosstabColumns}" var="ctcolumn">                             
            <b:dataTableColumn>
                <h:outputText value="#{ctrow.crosstabRowsPK.rowName}" rendered="#{ctResultsBean.isFirstColumn(ctcolumn.columnNum)}"/>
                <h:outputText value="#{ctrow.getReturnCellByName(ctcolumn.crosstabColumnsPK.columnName).cellValue}" rendered="#{not ctResultsBean.isFirstColumn(ctcolumn.columnNum)}"/>                                                             
            </b:dataTableColumn>                             
        </c:forEach> 
</b:dataTable> 
tg47 commented 7 years ago

Sorry, I should have used code brackets when I wrote some of the code above. The header that I mention I use is something like this. `<f:facet name = "header"

Employee Name January February etc. The footer could be the same way. etc. `
tg47 commented 7 years ago

One more time to see if this formats corectly.

This is how the header is currently established.

<f:facet name="header">                            
    <tr>
     <th colspan="1"><h:outputText value="Total"/></th> 
        <th colspan="1"><h:outputText value="January"/></th>
        <th colspan="1"><h:outputText value="February"/></th>
        <th colspan="1"><h:outputText value="March"/></th>
        <th colspan="1"><h:outputText value="April"/></th>
        <th colspan="1"><h:outputText value="May"/></th>
        <th colspan="1"><h:outputText value="June"/></th>
        <th colspan="1"><h:outputText value="July"/></th>
        <th colspan="1"><h:outputText value="August"/></th>
        <th colspan="1"><h:outputText value="September"/></th>
        <th colspan="1"><h:outputText value="October"/></th>
        <th colspan="1"><h:outputText value="November"/></th>
        <th colspan="1"><h:outputText value="December"/></th>
        <th colspan="1"><h:outputText value="Total"/></th>
    <tr>
</f:facet>

This is how I believe the footer could be established.

<f:facet name="footer">                            
    <tr>
        <th colspan="1">Total</th>
        <th colspan="1"><h:outputText value="#{bean.januaryTotal}"/></th>
        <th colspan="1"><h:outputText value="#{bean.februaryTotal}"/></th>
        <th colspan="1"><h:outputText value="#{bean.marchTotal}"/></th>
        <th colspan="1"><h:outputText value="#{bean.aprilTotal}"/></th>
        <th colspan="1"><h:outputText value="#{bean.mayTotal}"/></th>
        <th colspan="1"><h:outputText value="#{bean.juneTotal}"/></th>
        <th colspan="1"><h:outputText value="#{bean.julyTotal}"/></th>
        <th colspan="1"><h:outputText value="#{bean.augustTotal}"/></th>
        <th colspan="1"><h:outputText value="#{bean.septemberTotal}"/></th>
        <th colspan="1"><h:outputText value="#{bean.octoberTotal}"/></th>
        <th colspan="1"><h:outputText value="#{bean.novemberTotal}"/></th>
        <th colspan="1"><h:outputText value="#{bean.decememberTotal}"/></th>
        <th colspan="1"><h:outputText value="#{bean.allTotal}"/></th>
    </tr>
</f:facet>
chongma commented 7 years ago

Have you considered creating a model with POJOs to represent what you are trying to output? i always find if there is too much complexity in the xhtml then i need to revisit the data model. it is quite hard to understand your model but here is an example. i am not sure if this will work...

e.g. pojos

public class MyTableData implements Serializable {
    private List<String> header;
    private List<MyTableRow> row;
    private List<String> footer;
    ...getters
    ...setters
}
public class MyTableRow implements Serializable {
    private List<String> body;
    ...getters
    ...setters
}

e.g. bean

public class myBean {

private MyTableData myTableData;

public void onload(){
    myTableData = create();    
}

private MyTableData create() {
    MyTableData myTableData = new MyTableData();
    List<String> header = new ArrayList();
    header.add("January header");
    ....etc
    myTableData.setHeader(header);
    List<MyTableRow> row = new ArrayList();
    MyTableRow myTableRow = new MyTableRow();
    List<String> body = new ArrayList();
    body.add("January column data");
    ....etc
    myTableRow.setBody(body);
    row.add(myTableRow);
    List<String> footer = new ArrayList();
    footer.add("January footer");
    ....etc
    myTableData.setFooter(footer);
    return myTableData;
}
    ...getters
    ...setters
}

e.g. xhtml

// onload the bean
<b:dataTable var="row" value="#{myBean.myTableData.row}">
<c:forEach var="header" items="#{myBean.myTableData.header" varStatus="varStatus"> 
<b:dataTableColumn>
<f:facet name="header">#{header}</f:facet>
#{row.body[varStatus.index]}
<f:facet name="footer">#{myBean.myTableData.footer[varStatus.index]}</f:facet>
</b:dataTableColumn>
</c:forEach>
</b:dataTable>
tg47 commented 6 years ago

I’d just like to clarify a little more the feature we are requesting.

In the Bootsfaces showcase for Datatables under the section “Defining the Header” there is a code example that allows the header to be defined outside the tag. This example shows that the heading can be developed using the tag . This is especially helpful when there is more than one row in the heading. In my case the table I am creating has two rows as follows:

rowheading

What we are requesting, is that a footer row can be created in the same way outside the using the tag . This will be especially helpful in cases where the user wants to create a row of column totals and place it in the footer. Using the showcase example, I show below how the code could look.

  <b:dataTable value="#{carPool.carPool}"
               var="car"
               page-length="5"
               page-length-menu="5,10,20">
    <f:facet name="header">
       <tr>
          <th colspan="2" rowspan="2">Car</th>
          <th colspan="2">Appearance</th>
          <th colspan="2">Technical Data</th>
      </tr>
      <tr>
          <th>Color</th>
          <th>Year</th>
          <th>Price</th>
          <th>Power</th>
       </tr>
     </f:facet>
     <b:dataTableColumn value="#{car.brand}" />
     <b:dataTableColumn value="#{car.type}" />
     <b:dataTableColumn value="#{car.color}" />
     <b:dataTableColumn value="#{car.year}"  order="asc" />
     <b:dataTableColumn value="#{car.price}" />
     <b:dataTableColumn value="#{car.enginePower}"/>
     <f:facet name="footer">
        <tr>
          <td><h:outputText value="#{carPool.brandcount}"/></td>
          <td><h:outputText value="#{carPool.typecount}"/></td>
          <td><h:outputText value="#{carPool.colorcount}"/></td>
          <td><h:outputText value="#{carPool.yearcount}"/></td>  
          <td><h:outputText value="#{carPool.pricetotal}"/></td> 
          <td><h:outputText value="#{carPool.enginecount}"/></td>                             
        </tr>
     </f:facet>
 </b:dataTable>

Right now we can't define the entire heading using just the tag because there are multiple rows in the heading. If I try to define the header as I did above and set the footer facet in the tag without the header it doesn't lay the footer rows out correctly.

Thanks

tg47 commented 6 years ago

Hello, I was able to get this working correctly following Matthew's guidance. The functionality does currently exist in Bootsfaces to create a footer row with totals.

I created the heading using the outside the .

For the footer I reworked my program logic to place the totals in the using the . I did not have to place any header information in the .

Thank you for your help Matthew.

chongma commented 6 years ago

Hi @tg47, I am glad you found a way to get it working. I still think that you are correct that if the header works in the way you expected then the footer should also. I will mark this as an enhancement for future consideration

stephanrauh commented 5 years ago

It seems we've simply forgotten to close the ticket. Doing it now.