11

I have been having issues with page breaks in tables. Thought I had a solution as it was working fine in this SO question:

Inserting a page break into of <table> in React app

This worked fine for a table with one column, but nowt that I am working with multiple columns, it is a mess.

Basically I have to include display: block to get the page break to work properly, but that makes it go from a well formatted table to this:

enter image description here

I have gone down the list in MDN just trying anything that might work.

https://developer.mozilla.org/en-US/docs/Web/CSS/display

Furthermore, page breaks are only working when on their own separate <tr> which is undesirable since it generates a blank page. Got this sorted out by moving the pagebreak to the <tr> instead of the <td>.

I haven't been able to resolve these issues; any suggestions on how to approach this problem?

Not sure how useful a JSFiddle will be given the printing issue, but here is the compiled HTML. I can never get JSFiddle working with React:

https://jsfiddle.net/5gz62d91/

Best would probably be the Github repo:

https://github.com/ishraqiyun77/page-breaks

Here is the code separately:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

import styles from '../assets/scss/app.scss';

class PageBreakIssues extends Component {

    // Render the data points
    renderDataPoint() {
        let dataPoint = [];
        for (let i = 1; i <= 3; i++) {
            let num = (Math.random() * 100).toFixed(2);
            dataPoint.push(
                <td className='data-point' key={ i }>
                    { num < 25 ? null : num }
                </td>
            )
        }
        return dataPoint;
    }

    // Start generating the row data
    renderDataRow() {
        let dataRow = [];
        for (let i = 1; i <= 5; i++) {
            dataRow.push(
                <tr key={ i }>
                    <td className='data-name' colSpan='3' key={i}>Test - { i }</td>
                    { this.renderDataPoint() }
                </tr>
            )
        }
        return dataRow;
    }

    // Start generating table sections with the section name
    // COMMENT THIS OUT TO TRY WITOUT ADDING A BLANK ROW
    renderSections() {
        let sections = [];
        for (let i = 1; i <= 10; i++) {
            sections.push(
                <tbody key={ i }>

                    <tr key={ i }>
                        <td colSpan='7' className='section-name' key={i} >
                            Section - { i }
                        </td>
                    </tr>
                    { this.renderDataRow() }
                    {
                        i % 2 === 0
                            ?
                            <tr className='pagebreak'>
                                <td colSpan='7'></td>
                            </tr>
                            :
                            null
                    }
                </tbody>
            )
        }   
        return sections;
    }

    // Start generating table sections with the section name
    // UNCOMMENT THIS SECTION TO TRY WITHOUT INSERT BLANK TR
    // renderSections() {
    //     let sections = [];
    //     for (let i = 1; i <= 10; i++) {
    //         sections.push(
    //             <tbody key={i}>
    //                 <tr key={i}>
    //                     <td colSpan='7' className={ i % 2 === 0? 'section-name pagebreak' : 'section-name'} key={i} >
    //                         Section - {i}
    //                     </td>
    //                 </tr>
    //                 {this.renderDataRow()}
    //             </tbody>
    //         )
    //     }
    //     return sections;
    // }

    // Render the table with <th>
    render() {
        return (
            <table>
                <thead>
                    <tr>
                        <th colSpan='3'>Results</th>
                        <th>1</th>
                        <th>2</th>
                        <th>3</th>
                    </tr>
                </thead>
                { this.renderSections() }
            </table>
        )
    }
}

ReactDOM.render(<PageBreakIssues />, document.getElementById('app'));

@mixin borders {
    border: 1px solid black;
}

%borders {
    @include borders;
}

table {
    border-spacing: 0;

    th {
        text-align: center;
    }

    tr {
        th{
            @extend %borders;
        }

        td {
            @extend %borders;
            &.data-name {
                padding: 3px 100px 3px 3px;
            }

            &.data-point {
                text-align: center;
                padding: 3px 10px;
            }

            &.section-name {
                background-color: #999;
            }
        }
    }
}

@media print {
    tr {
        display: block;
    }

    .pagebreak {
        break-before: always !important;
        page-break-before: always !important;
        page-break-inside: avoid !important;
    }
}
halfer
  • 19,824
  • 17
  • 99
  • 186
cjones
  • 8,384
  • 17
  • 81
  • 175
  • The posts [here](https://stackoverflow.com/questions/8712677/how-to-apply-css-page-break-to-print-a-table-with-lots-of-rows) and [here](https://stackoverflow.com/questions/47478539/printing-html-tables-preventing-rows-from-spanning-multiple-pages/47498775#47498775) may be relevant. – Kalnode Sep 02 '18 at 17:18

1 Answers1

10

I figure out an even more hard-coding method (so call perfectly solve your problem). I must said it is not elegant.

My method's main idea is changing tbody to display:block (as usual), but adding the .pagebreak to target tbody as well.

However, this method unattach tbody from the table and thus no longer align with thead. That's why I add a tr for printing thead, and remove the origin thead when print.

Added printing th, don't show in normal view

//Thead part, add a printing thead only shown in Print
//As originaly thead will has alloction problem
{ i % 2 === 1 ?
  <tr className='printing-thead'>
    <td colspan="3">Results</td>
    <td>1</td>
    <td>2</td>
    <td>3</td>
  </tr> : null
}
....
...
//Corrected Page break
</tbody>
<tbody class="pagebreak">
    <tr>
        <td colspan="7"></td>
    </tr>
</tbody>
<tbody>
...

Corresponding CSS

table {
  border-spacing: 0;
  table-layout: fixed;
  th {
    text-align: center;
  }
  tr {
    th {
      @extend %borders;
    }
    td {
      @extend %borders;
      &.data-name {
        padding: 3px 100px 3px 3px;
      }
      &.data-point {
        text-align: center;
        padding: 3px 10px;
      }
      &.section-name {
        background-color: #999;
      }
    }
  }
  tr.printing-thead {
    display: none;
  }
}

@media print {
  thead {
    display: none;
  }
  tbody {
    display: block;
    tr.printing-thead {
      display: contents;
      font-weight: bold;
      text-align: center;
    }
  }
  .pagebreak {
    height: 0px;
    break-before: always !important;
    page-break-before: always !important;
    page-break-inside: avoid !important;
    td {
      display: none;
    }
  }
}

The JSfiddle.

And the react version

JSfiddle React Version

MT-FreeHK
  • 2,462
  • 1
  • 13
  • 29
  • 1
    Late response due to being out-of-office, sorry. Thanks for the help! This is does resolve the issue asked about. However, it presents two problems one of which you talked about: the `` and `` columns don't line up; the header doesn't repeat on each page. I'll play with this some more to see what I can do. Thanks! – cjones Aug 31 '18 at 15:25
  • 1
    @sockpuppet, you should better not choose as ans first. There may be someone have better solution, I am looking for it too. – MT-FreeHK Aug 31 '18 at 15:54
  • @sockpuppet , I update a solution solve the problems you mentioned. – MT-FreeHK Sep 03 '18 at 02:01
  • Hi, would be able to show the `render()` for the component that rendered the HTML in the JSFiddle? I'm not getting the same results and actually running into issues where it is hiding sections where the page break is. There apparently needs to be a conditional where there is a `` in both the `true` and `false` conditions, but one contains the `pagebreak` class name. This however is also skipping the sections. Having a ternary on the `` also causes it to hide sections where the page break is. – cjones Sep 13 '18 at 18:34
  • 1
    @sockpuppet , I update the react version jsfiddle in the content, please take a look. – MT-FreeHK Sep 17 '18 at 02:20