@@ -440,3 +440,203 @@ addNewColumn() {
440440 }
441441}
442442` ` `
443+
444+ ## Row Detail with Inner Grid
445+
446+ You can also add an inner grid inside a Row Detail, however there are a few things to know off and remember. Any time a Row Detail is falling outside the main grid viewport, it will be unmounted and until it comes back into the viewport which is then remounted. The process of unmounting and remounting means that Row Detail previous states aren't preserved, however you could use Grid State & Presets to overcome this problem.
447+
448+ ##### Component
449+
450+ Main Grid Component
451+
452+ ` ` ` tsx
453+ import React from ' react' ;
454+ import { type Column , ExtensionName , type GridOption , SlickgridReact , type SlickgridReactInstance , SlickRowDetailView , } from ' slickgrid-react' ;
455+
456+ import { Preload } from ' ./preload' ;
457+ import { type Distributor , InnerGridComponent , type OrderData } from ' ./inner-grid' ;
458+
459+ interface State extends BaseSlickGridState { }
460+
461+ export default class Example45 extends React .Component <Props , State > {
462+ reactGrid! : SlickgridReactInstance ;
463+ constructor (public readonly props : Props ) {
464+ super (props );
465+
466+ this .state = {
467+ gridOptions: undefined ,
468+ columnDefinitions: [],
469+ dataset: this .getData (),
470+ };
471+ }
472+
473+ get rowDetailInstance() {
474+ return this .reactGrid ?.extensionService .getExtensionInstanceByName (ExtensionName .rowDetailView );
475+ }
476+
477+ componentDidMount() {
478+ this .defineGrid ();
479+ }
480+
481+ reactGridReady(reactGrid : SlickgridReactInstance ) {
482+ this .reactGrid = reactGrid ;
483+ }
484+
485+ getColumnDefinitions(): Column [] {
486+ return [/* ... */ ];
487+ }
488+
489+ defineGrid() {
490+ const columnDefinitions = this .getColumnDefinitions ();
491+ const gridOptions = this .getGridOptions ();
492+
493+ this .setState ((props : Props , state : any ) => {
494+ return { ... state , columnDefinitions , gridOptions };
495+ });
496+ }
497+
498+ getGridOptions(): GridOption {
499+ return {
500+ enableRowDetailView: true ,
501+ rowSelectionOptions: {
502+ selectActiveRow: true
503+ },
504+ preRegisterExternalExtensions : (pubSubService ) => {
505+ // Row Detail View is a special case because of its requirement to create extra column definition dynamically
506+ // so it must be pre-registered before SlickGrid is instantiated, we can do so via this option
507+ const rowDetail = new SlickRowDetailView (pubSubService as EventPubSubService );
508+ return [{ name: ExtensionName .rowDetailView , instance: rowDetail }];
509+ },
510+ rowDetailView: {
511+ process : (item : any ) => simulateServerAsyncCall (item ),
512+ loadOnce: false , // IMPORTANT, you can't use loadOnce with inner grid because only HTML template are re-rendered, not JS events
513+ panelRows: 10 ,
514+ preloadComponent: PreloadComponent ,
515+ viewComponent: InnerGridComponent ,
516+ },
517+ };
518+ }
519+
520+ render() {
521+ return ! this .state .gridOptions ? ' ' : (
522+ < div id = " demo-container" className = " container-fluid" >
523+ < SlickgridReact gridId = " grid45"
524+ columnDefinitions = {this.state.columnDefinitions }
525+ gridOptions = {this.state.gridOptions }
526+ dataset = {this.state.dataset }
527+ onReactGridCreated = {$event => this .reactGridReady ($event .detail )}
528+ / >
529+ < / div >
530+ );
531+ }
532+ }
533+ ` ` `
534+
535+ Now, let's define our Inner Grid Component
536+
537+ ` ` ` tsx
538+ import React from ' react' ;
539+ import { type Column , type GridOption , type GridState , type RowDetailViewProps , SlickgridReact , type SlickgridReactInstance } from ' slickgrid-react' ;
540+
541+ import type MainGrid from ' ./MainGrid' ;
542+
543+ export interface Distributor { /* ... */ }
544+ export interface OrderData { /* ... */ }
545+
546+ interface State {
547+ innerGridOptions?: GridOption ;
548+ innerColDefs : Column [];
549+ innerDataset : any [];
550+ }
551+ interface Props { }
552+
553+ export class MainGridDetailView extends React .Component <RowDetailViewProps <Distributor , typeof MainGrid >, State > {
554+ reactGrid! : SlickgridReactInstance ;
555+ innerGridClass = ' ' ;
556+
557+ constructor (public readonly props : RowDetailViewProps <Distributor , typeof MainGrid >) {
558+ super (props );
559+ this .state = {
560+ innerGridOptions: undefined ,
561+ innerColDefs: [],
562+ innerDataset: [... props .model .orderData ],
563+ };
564+ this .innerGridClass = ` row-detail-${this .props .model .id } ` ;
565+ }
566+
567+ componentDidMount() {
568+ this .defineGrid ();
569+ }
570+
571+ getColumnDefinitions(): Column [] {
572+ return [
573+ { id: ' orderId' , field: ' orderId' , name: ' Order ID' , filterable: true , sortable: true },
574+ { id: ' shipCity' , field: ' shipCity' , name: ' Ship City' , filterable: true , sortable: true },
575+ { id: ' freight' , field: ' freight' , name: ' Freight' , filterable: true , sortable: true , type: ' number' },
576+ { id: ' shipName' , field: ' shipName' , name: ' Ship Name' , filterable: true , sortable: true },
577+ ];
578+ }
579+
580+ defineGrid() {
581+ const innerColDefs = this .getColumnDefinitions ();
582+ const innerGridOptions = this .getGridOptions ();
583+
584+ this .setState ((props : Props , state : any ) => {
585+ return {
586+ ... state ,
587+ innerColDefs ,
588+ innerGridOptions ,
589+ };
590+ });
591+ }
592+
593+ getGridOptions(): GridOption {
594+ // OPTIONALLY reapply Grid State as Presets before unmounting the compoment
595+ const gridStateStr = sessionStorage .getItem (` gridstate_${innerGridClass .value } ` );
596+ let gridState: GridState | undefined ;
597+ if (gridStateStr ) {
598+ gridState = JSON .parse (gridStateStr );
599+ }
600+
601+ return {
602+ autoResize: {
603+ container: ` .${this .innerGridClass } ` ,
604+ },
605+ enableFiltering: true ,
606+ enableSorting: true ,
607+ enableCellNavigation: true ,
608+ datasetIdPropertyName: ' orderId' , // reapply grid state presets
609+ presets: gridState ,
610+ };
611+ }
612+
613+ // OPTIONALLY save Grid State before unmounting the compoment
614+ handleBeforeGridDestroy() {
615+ if (this .props .model .isUsingInnerGridStatePresets ) {
616+ const gridState = this .reactGrid .gridStateService .getCurrentGridState ();
617+ sessionStorage .setItem (` gridstate_${this .innerGridClass } ` , JSON .stringify (gridState ));
618+ }
619+ }
620+
621+ reactGridReady(reactGrid : SlickgridReactInstance ) {
622+ this .reactGrid = reactGrid ;
623+ }
624+
625+ render() {
626+ return (
627+ < div className = {` ${this .innerGridClass } ` }>
628+ <h4 >Order Details (id : {this.props.model.id })< / h4 >
629+ < div className = " container-fluid" >
630+ {!this .state .showGrid ? ' ' : <SlickgridReact gridId = {` innergrid-${this .props .model .id } ` }
631+ columnDefinitions = {this.state.innerColDefs }
632+ gridOptions = {this.state.innerGridOptions }
633+ dataset = {this.state.innerDataset }
634+ onReactGridCreated = {$event => this .reactGridReady ($event .detail )}
635+ onBeforeGridDestroy = {() => this.handleBeforeGridDestroy()}
636+ />}
637+ < / div >
638+ < / div >
639+ );
640+ }
641+ }
642+ ` ` `
0 commit comments