@@ -154,10 +154,11 @@ export class IgxPdfExporterService extends IgxBaseExporter {
154154 const childRecords = [ ] ;
155155 let childOwner = null ;
156156
157- // Collect all child records that belong to this parent
157+ // Collect only direct child records (next level) that belong to this parent
158158 let j = i + 1 ;
159159 while ( j < data . length && data [ j ] . owner !== DEFAULT_OWNER && data [ j ] . level > record . level ) {
160- if ( ! data [ j ] . hidden ) {
160+ // Only include direct children (one level deeper)
161+ if ( data [ j ] . level === record . level + 1 && ! data [ j ] . hidden ) {
161162 childRecords . push ( data [ j ] ) ;
162163 if ( ! childOwner ) {
163164 childOwner = data [ j ] . owner ;
@@ -168,48 +169,20 @@ export class IgxPdfExporterService extends IgxBaseExporter {
168169
169170 // If there are child records, draw a child table
170171 if ( childRecords . length > 0 && childOwner ) {
171- const childColumns = this . _ownersMap . get ( childOwner ) ?. columns . filter (
172- col => col . field && ! col . skip && col . headerType === ExportHeaderType . ColumnHeader
173- ) || [ ] ;
174-
175- if ( childColumns . length > 0 ) {
176- // Add some spacing before child table
177- yPosition += 5 ;
178-
179- // Check if child table fits on current page
180- const childTableHeight = headerHeight + ( childRecords . length * rowHeight ) + 10 ;
181- if ( yPosition + childTableHeight > pageHeight - margin ) {
182- pdf . addPage ( ) ;
183- yPosition = margin ;
184- }
185-
186- // Draw child table with indentation
187- const childTableWidth = usableWidth - childTableIndent ;
188- const childColumnWidth = childTableWidth / childColumns . length ;
189- const childTableX = margin + childTableIndent ;
190-
191- // Draw child table headers
192- this . drawTableHeaders ( pdf , childColumns , childTableX , yPosition , childColumnWidth , headerHeight , childTableWidth , options ) ;
193- yPosition += headerHeight ;
194-
195- // Draw child table rows
196- childRecords . forEach ( ( childRecord ) => {
197- // Check if we need a new page
198- if ( yPosition + rowHeight > pageHeight - margin ) {
199- pdf . addPage ( ) ;
200- yPosition = margin ;
201- // Redraw headers on new page
202- this . drawTableHeaders ( pdf , childColumns , childTableX , yPosition , childColumnWidth , headerHeight , childTableWidth , options ) ;
203- yPosition += headerHeight ;
204- }
205-
206- this . drawDataRow ( pdf , childRecord , childColumns , childTableX , yPosition , childColumnWidth , rowHeight , 0 , options ) ;
207- yPosition += rowHeight ;
208- } ) ;
209-
210- // Add spacing after child table
211- yPosition += 5 ;
212- }
172+ yPosition = this . drawHierarchicalChildren (
173+ pdf ,
174+ data ,
175+ childRecords ,
176+ childOwner ,
177+ yPosition ,
178+ margin ,
179+ childTableIndent ,
180+ usableWidth ,
181+ pageHeight ,
182+ headerHeight ,
183+ rowHeight ,
184+ options
185+ ) ;
213186
214187 // Skip the child records we just processed
215188 i = j - 1 ;
@@ -305,6 +278,112 @@ export class IgxPdfExporterService extends IgxBaseExporter {
305278 return yPosition ;
306279 }
307280
281+ private drawHierarchicalChildren (
282+ pdf : jsPDF ,
283+ allData : IExportRecord [ ] ,
284+ childRecords : IExportRecord [ ] ,
285+ childOwner : string ,
286+ yPosition : number ,
287+ margin : number ,
288+ indentPerLevel : number ,
289+ usableWidth : number ,
290+ pageHeight : number ,
291+ headerHeight : number ,
292+ rowHeight : number ,
293+ options : IgxPdfExporterOptions
294+ ) : number {
295+ const childColumns = this . _ownersMap . get ( childOwner ) ?. columns . filter (
296+ col => col . field && ! col . skip && col . headerType === ExportHeaderType . ColumnHeader
297+ ) || [ ] ;
298+
299+ if ( childColumns . length === 0 ) {
300+ return yPosition ;
301+ }
302+
303+ // Add some spacing before child table
304+ yPosition += 5 ;
305+
306+ // Check if child table fits on current page
307+ const childTableHeight = headerHeight + ( childRecords . length * rowHeight ) + 10 ;
308+ if ( yPosition + childTableHeight > pageHeight - margin ) {
309+ pdf . addPage ( ) ;
310+ yPosition = margin ;
311+ }
312+
313+ // Draw child table with indentation
314+ const childTableWidth = usableWidth - indentPerLevel ;
315+ const childColumnWidth = childTableWidth / childColumns . length ;
316+ const childTableX = margin + indentPerLevel ;
317+
318+ // Draw child table headers
319+ this . drawTableHeaders ( pdf , childColumns , childTableX , yPosition , childColumnWidth , headerHeight , childTableWidth , options ) ;
320+ yPosition += headerHeight ;
321+
322+ // Process each child record
323+ let childIndex = 0 ;
324+ while ( childIndex < childRecords . length ) {
325+ const childRecord = childRecords [ childIndex ] ;
326+
327+ // Check if we need a new page
328+ if ( yPosition + rowHeight > pageHeight - margin ) {
329+ pdf . addPage ( ) ;
330+ yPosition = margin ;
331+ // Redraw headers on new page
332+ this . drawTableHeaders ( pdf , childColumns , childTableX , yPosition , childColumnWidth , headerHeight , childTableWidth , options ) ;
333+ yPosition += headerHeight ;
334+ }
335+
336+ this . drawDataRow ( pdf , childRecord , childColumns , childTableX , yPosition , childColumnWidth , rowHeight , 0 , options ) ;
337+ yPosition += rowHeight ;
338+
339+ // Check if this child record has its own children (next level in hierarchy)
340+ const childRecordIndex = allData . indexOf ( childRecord ) ;
341+ if ( childRecordIndex >= 0 && childRecordIndex + 1 < allData . length ) {
342+ // Look for grandchildren
343+ const grandchildRecords : IExportRecord [ ] = [ ] ;
344+ let grandchildOwner : string | null = null ;
345+ let k = childRecordIndex + 1 ;
346+
347+ // Collect all grandchildren that belong to this child
348+ while ( k < allData . length && allData [ k ] . level > childRecord . level ) {
349+ // Only include direct children (next level)
350+ if ( allData [ k ] . level === childRecord . level + 1 && ! allData [ k ] . hidden ) {
351+ grandchildRecords . push ( allData [ k ] ) ;
352+ if ( ! grandchildOwner ) {
353+ grandchildOwner = allData [ k ] . owner ;
354+ }
355+ }
356+ k ++ ;
357+ }
358+
359+ // Recursively draw grandchildren if they exist
360+ if ( grandchildRecords . length > 0 && grandchildOwner ) {
361+ yPosition = this . drawHierarchicalChildren (
362+ pdf ,
363+ allData ,
364+ grandchildRecords ,
365+ grandchildOwner ,
366+ yPosition ,
367+ margin ,
368+ indentPerLevel + 30 , // Increase indentation for next level
369+ usableWidth ,
370+ pageHeight ,
371+ headerHeight ,
372+ rowHeight ,
373+ options
374+ ) ;
375+ }
376+ }
377+
378+ childIndex ++ ;
379+ }
380+
381+ // Add spacing after child table
382+ yPosition += 5 ;
383+
384+ return yPosition ;
385+ }
386+
308387 private drawTableHeaders (
309388 pdf : jsPDF ,
310389 columns : any [ ] ,
0 commit comments