Prince
Prince

Reputation: 75

Nested tables in a pdf using jspdf and jspdf-autotable

How to achieve nested tables in a PDF using jspdf and jspadf-autotable? Something similar to the picture below:

Nested tables in pdf

Upvotes: 4

Views: 14313

Answers (2)

ady arabiat
ady arabiat

Reputation: 1279

To add nested table using jspdf and jspdf-autotable and to make it dynamic so the data in both table and nested table are coming from a service or from the user: I am using React but you can implement it in vanila JS or any other library or framework.

1.add the main table in the "html page" or "jsx" you can map through array instead of adding static table rows:

<div className="App">
        <button
            onClick={downloadPDF}
            style={{
                marginTop: 20,
                background: 'blue',
                color: 'white',
                width: '200px',
                height: '50px',
            }}
        >
            Download as PDF
        </button>
        <table id="table" style={{ display: 'none' }}>
            <thead>
                <tr>
                    <th align="center">Column1</th>
                    <th align="center">Column2</th>
                    <th align="center">Column3</th>
                    <th align="center">Column4</th>
                    <th align="center">Column5-Table</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td align="center">1</td>
                    <td>row1</td>
                    <td>row1</td>
                    <td>row1</td>
                    <td></td>
                </tr>
                <tr>
                    <td align="center">2</td>
                    <td>row2</td>
                    <td>row2</td>
                    <td>row2</td>
                    <td></td>
                </tr>
                <tr>
                    <td align="center">1</td>
                    <td>row3</td>
                    <td>row3</td>
                    <td>row3</td>
                    <td></td>
                </tr>
                <tr>
                    <td align="center">3</td>
                    <td>row4</td>
                    <td>row4</td>
                    <td>row4</td>
                    <td></td>
                </tr>
            </tbody>
        </table>
    </div>
  1. downloadPDF Function in here we need to track the index to give the nested table the right data "not to be static or same data for all the nested tables":
const downloadPDF = () => {
        const doc = new jsPDF();
        doc.autoTable({
            headStyles: {
                valign: 'middle',
                halign: 'center',
            },
            html: '#table',
            didDrawCell: function (data) {
                let neastedTableData = [
                    [
                        ['32423423', 'ady arabiat-1', 'false', '2022-07-07'],
                        ['32423423', 'ady arabiat-1', 'false', '2022-07-07'],
                    ],
                    [
                        ['32423423', 'ady arabiat-2', 'false', '2022-07-07'],
                        ['32423423', 'ady arabiat-2', 'false', '2022-07-07'],
                    ],
                    [
                        ['32423423', 'ady arabiat-3', 'false', '2022-07-07'],
                        ['32423423', 'ady arabiat-3', 'false', '2022-07-07'],
                        ['32423423', 'ady arabiat-3', 'false', '2022-07-07'],
                        ['32423423', 'ady arabiat-3', 'false', '2022-07-07'],
                        ['32423423', 'ady arabiat-3', 'false', '2022-07-07'],
                    ],
                    [
                        ['32423423', 'ady arabiat-4', 'false', '2022-07-07'],
                        ['32423423', 'ady arabiat-4', 'false', '2022-07-07'],
                        ['32423423', 'ady arabiat-4', 'false', '2022-07-07'],
                        ['32423423', 'ady arabiat-4', 'false', '2022-07-07'],
                        ['32423423', 'ady arabiat-4', 'false', '2022-07-07'],
                    ],
                    [
                        ['32423423', 'ady arabiat-5', 'false', '2022-07-07'],
                        ['32423423', 'ady arabiat-5', 'false', '2022-07-07'],
                        ['32423423', 'ady arabiat-5', 'false', '2022-07-07'],
                    ],
                    [
                        ['32423423', 'ady arabiat-6', 'false', '2022-07-07'],
                        ['32423423', 'ady arabiat-6', 'false', '2022-07-07'],
                        ['32423423', 'ady arabiat-6', 'false', '2022-07-07'],
                    ],
                ];
                if (data.column.dataKey === 4 && data.cell.section === 'body') {
                    let index = data.row.index; //check the index so you add the data for the nested Table dynamically depends on which row you are in
                    doc.autoTable({
                        head: [
                            [
                                'N-Column1',
                                'N-Column2',
                                'N-Column3',
                                'N-Column4',
                            ],
                        ],
                        body: neastedTableData[index], //index here
                        startY: data.cell.y + 2,
                        margin: {
                            left: data.cell.x + data.cell.padding('left'),
                        },
                        tableWidth: 'wrap',
                        theme: 'grid',
                        styles: {
                            fontSize: 7,
                            cellPadding: 2,
                        },
                    });
                }
            },
            columnStyles: {
                4: { cellWidth: 85 },
            },
            bodyStyles: {
                minCellHeight: 45,
            },
        });
        doc.save('table.pdf');
    };

Upvotes: 0

Simon Bengtsson
Simon Bengtsson

Reputation: 8151

There is no native support for having nested tables in jspdf-autotable but you can draw any content (including other autotables) with the didDrawCell hook.

var elem = document.getElementById("generate");
elem.onclick = function () {
var doc = new jsPDF();
doc.autoTable({
    html: '#table',
    didDrawCell: function (data) {
        if (data.column.dataKey === 5 && data.cell.section === 'body') {
            doc.autoTable({
                head: [["One", "Two", "Three", "Four"]],
                body: [
                    ["1", "2", "3", "4"],
                    ["1", "2", "3", "4"],
                    ["1", "2", "3", "4"],
                    ["1", "2", "3", "4"]
                ],
                startY: data.cell.y + 2,
                margin: {left: data.cell.x + data.cell.padding('left')},
                tableWidth: 'wrap',
                theme: 'grid',
                styles: {
                    fontSize: 7,
                    cellPadding: 1,
                }
            });
        }
    },
    columnStyles: {
        5: {cellWidth: 40}
    },
    bodyStyles: {
        minCellHeight: 30
    }
});
doc.save('table.pdf');
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.2.3/jspdf.plugin.autotable.min.js"></script>
<button id="generate">Generate PDF</button>

<table id="table" style="display: none;">
    <thead>
    <tr>
        <th>ID</th>
        <th>First name</th>
        <th>Last name</th>
        <th>Email</th>
        <th>Country</th>
        <th>Table</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td align="right">1</td>
        <td>Donna</td>
        <td>Moore</td>
        <td>[email protected]</td>
        <td>China</td>
        <td></td>
    </tr>
    <tr>
        <td align="right">2</td>
        <td>Janice</td>
        <td>Henry</td>
        <td>[email protected]</td>
        <td>Ukraine</td>
        <td></td>
    </tr>
    <tr>
        <td align="right">3</td>
        <td>Ruth</td>
        <td>Wells</td>
        <td>[email protected]</td>
        <td>Trinidad and Tobago</td>
        <td></td>
    </tr>
    <tr>
        <td align="right">4</td>
        <td>Jason</td>
        <td>Ray</td>
        <td>[email protected]</td>
        <td>Brazil</td>
        <td></td>
    </tr>
    <tr>
        <td align="right">5</td>
        <td>Jane</td>
        <td>Stephens</td>
        <td>[email protected]</td>
        <td>United States</td>
        <td></td>
    </tr>
    <tr>
        <td align="right">6</td>
        <td>Adam</td>
        <td>Nichols</td>
        <td>[email protected]</td>
        <td>Canada</td>
        <td></td>
    </tr>
    </tbody>
</table>

Upvotes: 14

Related Questions