By default, exporting a Master Detail grid includes the master rows but not their detail grids. Use getCustomContentBelowRow to return a PDF representation of the detail data that should be inserted below each master row.
Exporting Master And Detail Rows Copy Link
getCustomContentBelowRow receives the master row node and returns PdfCell[][]. Build these rows from the detail data stored on the master record:
<ag-grid-vue
:defaultPdfExportParams="defaultPdfExportParams"
/* other grid options ... */>
</ag-grid-vue>
this.defaultPdfExportParams = {
getCustomContentBelowRow: (params) => {
const records = params.node.data.callRecords;
return [
[
{ data: { value: 'Call ID' } },
{ data: { value: 'Direction' } },
{ data: { value: 'Number' } },
{ data: { value: 'Duration / Switch Code' } },
],
...records.map((record) => [
{ data: { value: String(record.callId) } },
{ data: { value: record.direction } },
{ data: { value: record.number } },
{ data: { value: `${record.duration}s / ${record.switchCode}` } },
]),
];
},
};This approach does not create or export a separate detail-grid instance. It works whether the detail row is expanded or collapsed and avoids creating every detail grid during export.
Detail-grid behaviour is not applied automatically. If detailGridOptions contains Value Getters, Value Formatters, sorting or filtering that should be represented in the PDF, apply the equivalent logic while building the custom rows.
Custom content uses the master table's exported column layout. Build a compact detail representation that fits the number and widths of the exported master columns.
The example below exports a heading, column headers and all call records below each master account row. The duration formatting used by the detail grid is reproduced when the PDF content is created.
import {
createApp,
defineComponent,
onBeforeMount,
ref,
shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
GridReadyEvent,
IDetailCellRendererParams,
ModuleRegistry,
PdfCell,
PdfCellStyle,
PdfExportParams,
ProcessRowGroupForExportParams,
enableDevValidations,
} from "ag-grid-community";
import {
ColumnMenuModule,
ContextMenuModule,
MasterDetailModule,
PdfExportModule,
} from "ag-grid-enterprise";
import { IAccount, ICallRecord } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
ModuleRegistry.registerModules([
ClientSideRowModelModule,
MasterDetailModule,
PdfExportModule,
ColumnMenuModule,
ContextMenuModule,
]);
const detailHeadingStyle: PdfCellStyle = {
backgroundColor: "#d9eaf7",
color: "#19486a",
fontWeight: "bold",
padding: 6,
};
const detailHeaderStyle: PdfCellStyle = {
backgroundColor: "#eef4f8",
color: "#243746",
fontWeight: "bold",
padding: 5,
};
function getDetailRows(
params: ProcessRowGroupForExportParams<IAccount>,
): PdfCell[][] {
const account = params.node.data;
if (!account) {
return [];
}
const rows: PdfCell[][] = [
[
{
data: { value: `Calls for ${account.name}` },
mergeAcross: 3,
style: detailHeadingStyle,
},
],
[
{ data: { value: "Call ID" }, style: detailHeaderStyle },
{ data: { value: "Direction" }, style: detailHeaderStyle },
{ data: { value: "Number" }, style: detailHeaderStyle },
{ data: { value: "Duration / Switch Code" }, style: detailHeaderStyle },
],
];
for (const record of account.callRecords) {
rows.push([
{ data: { value: String(record.callId) } },
{ data: { value: record.direction } },
{ data: { value: record.number } },
{ data: { value: `${record.duration}s / ${record.switchCode}` } },
]);
}
return rows;
}
const VueExample = defineComponent({
template: `
<div style="height: 100%">
<div class="example-wrapper">
<div class="controls">
<button v-on:click="onBtExport()">Export to PDF</button>
</div>
<ag-grid-vue
style="width: 100%; height: 100%;"
@grid-ready="onGridReady"
:columnDefs="columnDefs"
:defaultColDef="defaultColDef"
:masterDetail="true"
:detailCellRendererParams="detailCellRendererParams"
:defaultPdfExportParams="defaultPdfExportParams"
:rowData="rowData"></ag-grid-vue>
</div>
</div>
`,
components: {
"ag-grid-vue": AgGridVue,
},
setup(props) {
const gridApi = shallowRef<GridApi<IAccount> | null>(null);
const columnDefs = ref<ColDef[]>([
{ field: "name", cellRenderer: "agGroupCellRenderer", minWidth: 180 },
{ field: "account" },
{ field: "calls" },
{ field: "minutes", valueFormatter: (params) => `${params.value}m` },
]);
const defaultColDef = ref<ColDef>({
flex: 1,
minWidth: 110,
});
const detailCellRendererParams = ref({
detailGridOptions: {
columnDefs: [
{ field: "callId" },
{ field: "direction" },
{ field: "number", minWidth: 150 },
{ field: "duration", valueFormatter: (params) => `${params.value}s` },
{ field: "switchCode", minWidth: 150 },
],
defaultColDef: {
flex: 1,
},
},
getDetailRowData: (params) => {
params.successCallback(params.data.callRecords);
},
} as IDetailCellRendererParams<IAccount, ICallRecord>);
const defaultPdfExportParams = ref<PdfExportParams>({
columnWidth: "auto",
getCustomContentBelowRow: getDetailRows,
});
const rowData = ref<IAccount[]>(null);
function onBtExport() {
gridApi.value.exportDataAsPdf();
}
const onGridReady = (params: GridReadyEvent) => {
gridApi.value = params.api;
const updateData = (data) => {
rowData.value = data.slice(0, 3);
};
fetch("https://www.ag-grid.com/example-assets/master-detail-data.json")
.then((resp) => resp.json())
.then((data) => updateData(data));
};
return {
gridApi,
columnDefs,
defaultColDef,
detailCellRendererParams,
defaultPdfExportParams,
rowData,
onGridReady,
onBtExport,
};
},
});
const app = createApp(VueExample);
app.mount("#app");
.example-wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
.controls {
margin-bottom: 8px;
}
#myGrid {
flex: 1 1 0px;
width: 100%;
}
API Copy Link
Export Options Copy Link
See below the functions on the PdfExportParams interface to customise exported grid values.
A callback function to return content to be inserted below a row in the export. |
PdfCell Copy Link
Properties available on the PdfCell interface.
The data that will be added to the cell. |
The number of cells to span across (1 means span 2 columns). |
Optional styling for the cell.
|
PdfCellData Copy Link
Properties available on the PdfCellData interface.
The value of the cell. |
External URI opened when the exported cell text is selected. |
Image rendered alongside the cell value. |
ProcessRowGroupForExportParams Copy Link
Properties available on the ProcessRowGroupForExportParams<TData = any, TContext = any> interface.
Row node. |
The grid column |
The grid api. |
Application context as set on gridOptions.context. |