UNPKG

@edugouvfr/ngx-dsfr-ext

Version:

NgxDsfrExt est une extension au package @edugouvfr/ngx-dsfr (portage Angular des éléments DSFR)

541 lines 133 kB
import { ChangeDetectionStrategy, Component, ContentChild, ElementRef, EventEmitter, Input, Output, ViewChild, ViewEncapsulation, forwardRef, } from '@angular/core'; import { Language, newUniqueId } from '@edugouvfr/ngx-dsfr'; import { AgGridAngular } from 'ag-grid-angular'; import { ReplaySubject } from 'rxjs'; import { AG_GRID_LOCALE_FR } from './i18n/grid.fr'; import { MESSAGES_EN } from './i18n/messages.en'; import { MESSAGES_FR } from './i18n/messages.fr'; import { DsfrGridModeConst, EduRemoteAgGridApi, } from './interfaces/remote-ag-grid-api'; import * as i0 from "@angular/core"; import * as i1 from "@edugouvfr/ngx-dsfr"; import * as i2 from "@angular/common"; import * as i3 from "ag-grid-angular"; import * as i4 from "./directives/remote-ag-grid.directive"; export class DsfrGridComponent { constructor(i18n) { this.i18n = i18n; /** Nombre d'éléments affichés par page */ this.pageSize = 20; /** Mode de la grid: données côté client ou serveur (défaut client) */ this.mode = DsfrGridModeConst.CLIENT; /** Options des colonnes par défaut (cf. https://www.ag-grid.com/angular-data-grid/column-properties/ ) */ this.defaultColDef = { suppressHeaderMenuButton: true, sortable: true, filter: false, resizable: false, filterParams: { maxNumConditions: 1, }, }; /** Afficher un texte par-dessus la grid pendant le chargement */ this.showLoadingOverlay = true; /** Redéfinir le template de chargement */ //FIXME: nommage non consistant, à déprécier au profit de `overlayLoadingTemplate` this.loadingOverlayTemplate = undefined; /** Redéfinir le template aucun résultat. /!\ L'id de ce container doit être passé à idNoRowsTemplate */ this.overlayNoRowsTemplate = undefined; /** Id du template overlayNoRowsTemplate contenant le texte utilisé pour le aria-describedby */ this.idNoRowsTemplate = 'no-data-container'; /** Calcul dynamique de la hauteur des lignes pour afficher le contenu des cellules sur plusieurs lignes (uniquement utilisé en serverSide). * Déconseillé d'utiliser si le nombre de lignes par pages est élevé, peut causer des problèmes de performance d'affichage. */ this.autoRowsHeight = false; /** Afficher le bouton d'action exporter au format CSV (uniqument si headerActionsTemplate non défini) */ this.showExportCsv = false; /** Afficher la pagination */ this.showPagination = true; /** Afficher le total de lignes */ this.showFooterResult = true; /** Mise à jour et application du tri des colonnes */ this.sortChanged = new EventEmitter(); /** Callback apres l'initialisation de la grid, retourne l'accès à l'API de agGrid */ this.gridReady = new EventEmitter(); /** Callback avant la destruction de la grid (destruction du composant), permet de récuperer le state */ this.gridPreDestroyed = new EventEmitter(); /** Mise à jour et application des filtres */ this.filterChanged = new EventEmitter(); /** Sélection d'une cellule du tableau */ this.cellSelect = new EventEmitter(); /** Sélection ou déselection d'une ligne du tableau. Emission de l'évènement (RowSelectedEvent) et des noeuds sélectionnés (IRowNode[]) */ this.rowSelect = new EventEmitter(); /** La sélection des lignes a changé. Emission de l'évènement (SelectionChangedEvent) et des noeuds sélectionnés (IRowNode[]) */ this.selectionChange = new EventEmitter(); /** Indique une mise à jour nécessaire des données suite à un changement d'affichage (pagination, tri ou filtres). Si données côté serveur. */ this.dataChange = new EventEmitter(); /** Callback après chaque changement des lignes affichées (modelUpdated) */ this.dataRender = new EventEmitter(); /** Callback après appel à l'api en cas d'erreur de celle-ci */ this.dataFail = new EventEmitter(); /** Evenement de fin d'édition d'une cellule */ this.cellEditingStopped = new EventEmitter(); /** Pagination */ /** Choix de taille de page (par défaut 10, 20, 50, 100). Pas d'affichage du select si non défini */ this.pageSizes = [ { value: 10, label: '10 lignes par page', }, { value: 20, label: '20 lignes par page', }, { value: 50, label: '50 lignes par page', }, { value: 100, label: '100 lignes par page', }, ]; /** @internal Total résultats*/ this.totalElements = 0; /** @internal Page courante*/ this.currentPage = undefined; /** @internal Total pages */ this.totalPage = 0; /** @internal Index de la première ligne affichée */ this.startRow = 1; /** @internal Index de la première ligne affichée */ this.endRow = 1; /** @internal */ this.isLoadingServerSide = false; /** @internal en cas d'initalState avec pagination en mode serveur */ this.initialPagination = 0; this.loading = false; this.selectable = false; /** @internal */ this.resultSubject$ = new ReplaySubject(1); this.gridId ??= newUniqueId(); this.i18n.extendsLabelsBundle(Language.EN, MESSAGES_EN); this.i18n.extendsLabelsBundle(Language.FR, MESSAGES_FR); this.i18n.completeLangChange$.subscribe((code) => this.onLangChange(code)); } /** @internal */ get result$() { return this.resultSubject$.asObservable(); } /** Données renvoyées par l'API */ set result(value) { if (value && this.agGrid?.api) { this.totalElements = value.totalRecords; this.totalPage = this.calculateTotalPage(); this.resultSubject$.next(value); if (this.autoRowsHeight) { this.setHeightOnRows(); } this.isLoadingServerSide = false; this.forceReloadOnNoData(); this.loading = false; if (!this.gridOptions.autoSizeStrategy) { this.agGrid.api.sizeColumnsToFit(); } if (this.totalElements === 0) { this.agGrid.api.showNoRowsOverlay(); } } } ngOnInit() { this.captionId = 'caption-' + newUniqueId(); this.defaultColDef = { wrapText: this.autoRowsHeight ? true : false, filterParams: { maxNumConditions: 1, debounceMs: 1000 }, suppressFloatingFilterButton: true, suppressHeaderMenuButton: true, suppressHeaderFilterButton: true, resizable: false, ...this.defaultColDef, }; // gestion de la navigation au clavier par défaut if (this.defaultColDef && !this.defaultColDef?.suppressKeyboardEvent) this.suppressCellKeyboardEvent(); if (this.defaultColDef && !this.defaultColDef?.suppressHeaderKeyboardEvent) this.suppressHeaderKeyboardEvent(); this.gridOptions = { rowModelType: 'infinite', pagination: this.showPagination, suppressContextMenu: true, paginationPageSize: this.pageSize, maxBlocksInCache: 1, domLayout: this.fixedHeight ? 'normal' : 'autoHeight', enableCellTextSelection: true, suppressPaginationPanel: true, ensureDomOrder: true, rowBuffer: 20, unSortIcon: true, icons: { filter: '<i class="fr-icon-filter-line"></i>', sortAscending: '<i class="fr-icon-arrow-down-line"></i>', sortDescending: '<i class="fr-icon-arrow-up-line"></i>', sortUnSort: '<i class="fr-icon-arrow-up-down-line"></i> ', }, onGridPreDestroyed: ($event) => this.onGridPreDestroyed($event), ...this.gridOptions, getRowId: this.rowId ? (rowParams) => this.getRowNodeId(rowParams) : undefined, }; if (!this.initialState && this.gridOptions.initialState) { this.initialState = this.gridOptions.initialState; } this.selectable = !!this.gridOptions.rowSelection; this.initPagination(); if (this.mode === DsfrGridModeConst.CLIENT) { this.gridOptions.rowModelType = 'clientSide'; } else { this.gridOptions.cacheBlockSize = this.pageSize; this.isLoadingServerSide = true; } } /** * Au changement de paramètres des lignes affichées (pagination, filtre etc.), préparation des query params et envoi de l'evenement updateData * @param params IGetRowsParams paramètres modifiés * @internal */ prepareUpdateData(params) { if (this.showLoadingOverlay) this.loading = true; // Paramètres de la pagination if (!this.currentPage && this.initialState) { // si c'est le premier chargement du tableau et initialState renseigné, on remet les paramètres this.restoreInitialStateServer(params); } this.currentPage = Math.floor(params.startRow / this.pageSize) + 1; const httpParams = { limit: this.pageSize, offset: params.startRow }; // Ajout du tri if (params.sortModel && params.sortModel[0]) { this.addSort(params.sortModel, httpParams); } //Ajout des filtres if (params.filterModel) { this.addFilters(params.filterModel, httpParams); } this.dataChange.emit(httpParams); } /** * Erreur au retour de l'appel à l'api * @internal */ getDataError(err) { this.loading = false; if (this.totalElements === 0) { this.agGrid.api.showNoRowsOverlay(); } this.dataFail.emit(err); } /** * Modification et application du tri * @internal */ onSortChange(e) { this.sortChanged.emit(e); } /** * Modification et application des filtres * @internal */ onFilterChange(e) { this.filterChanged.emit(e); } /**@internal */ onCellEditingStop(e) { this.cellEditingStopped.emit(e); } /** * Après mise à jour des données * @internal */ onModelUpdated(e) { if (this.mode === DsfrGridModeConst.CLIENT) { this.loading = false; this.updatePagination(); } if (this.totalElements === 0) { this.loading = false; this.agGrid.api.showNoRowsOverlay(); } else { this.agGrid.api.hideOverlay(); } this.dataRender.emit(); } /** * Au redimensionnement de la fenêtre * @internal */ onGridSizeChanged(e) { if (this.autoRowsHeight && this.mode !== DsfrGridModeConst.CLIENT) { // recalculer la hauteur des lignes this.setHeightOnRows(); } // this.agGrid.api.sizeColumnsToFit(); disable automatic resize for perfs } /** * Au redimensionnement d'une colonne * @internal */ onColumnResized() { if (this.autoRowsHeight && this.mode !== DsfrGridModeConst.CLIENT) { // recalculer la hauteur des lignes this.setHeightOnRows(); } } /** * Premier affichage des données * /!\ bug connu ag-grid, firstDataRendered on infite mode is fired before data is rendered (AG-8812) * @internal */ onFirstDataRendered() { if (!this.gridOptions.autoSizeStrategy) { this.agGrid.api.sizeColumnsToFit(); } } /** * Initialisation de la grid * @param params * @internal */ onGridReady(params) { this.agGrid.api = params.api; if (this.caption) { this.agGrid.api.setGridAriaProperty('labelledby', this.captionId); } this.gridReady.emit(this.agGrid.api); } /** * Evenement clic sur une cellule * @internal */ onCellClicked(e) { this.cellSelect.emit(e); } /** * Evenement à la sélection ou déselection d'une ligne * @internal */ onRowSelected(e) { this.rowSelect.emit({ event: e, selectedNodes: this.agGrid.api?.getSelectedNodes() }); } /** * Evenement au changement de sélection * @internal */ onSelectionChanged(e) { this.selectionChange.emit({ event: e, selectedNodes: this.agGrid.api?.getSelectedNodes() }); } /** * Changement de page * @param e numéro de page * @internal */ onPage(e) { this.agGrid.api.paginationGoToPage(e - 1); if (this.mode === DsfrGridModeConst.CLIENT) { this.currentPage = e; } else if (this.agGrid.api.paginationGetCurrentPage() === 0 && this.initialPagination > 1) { this.initialPagination = 0; this.agGrid.api.refreshInfiniteCache(); } this.updateFooterPagination(); } /** * @internal */ onClickExportCsv() { this.agGrid.api.exportDataAsCsv(); } /** * @internal */ onChangePageSize(pageSize) { this.pageSize = pageSize; this.agGrid.api.updateGridOptions({ paginationPageSize: this.pageSize, cacheBlockSize: this.pageSize, }); this.updateFooterPagination(); } /** * @internal */ onGridPreDestroyed(e) { if (e?.state?.pagination?.page) { // fix current page number base 1 e.state.pagination.page = this.currentPage; } this.gridPreDestroyed.emit(e); } updateFooterPagination() { this.startRow = this.agGrid.api.getFirstDisplayedRowIndex() + 1; this.endRow = this.agGrid.api.getLastDisplayedRowIndex() + 1; this.updatePagination(); } updatePagination() { if (!this.showPagination) { this.totalElements = this.agGrid.api.getDisplayedRowCount(); } else { this.totalElements = this.agGrid.api.paginationGetRowCount(); this.totalPage = this.agGrid.api.paginationGetTotalPages(); this.currentPage = this.agGrid.api.paginationGetCurrentPage() + 1; } if (this.totalElements === 0) { this.agGrid.api.setGridAriaProperty('describedby', this.idNoRowsTemplate); } else { this.agGrid.api.setGridAriaProperty('describedby', null); } } calculateTotalPage() { return Math.ceil(this.totalElements / this.pageSize); } /* Retourne un identifiant unique selon la propriété définie par rowId */ getRowNodeId(row) { if (!row.data || !row.data[this.rowId]) { throw Error(`L'identifiant rowId '${this.rowId}' n'est pas défini pour une donnée`); } return row.data[this.rowId]; } /** Ajout du tri aux query params */ addSort(sortModel, httpParams) { httpParams.sort = sortModel; return httpParams; } /** * Ajout des filtres aux query params * @internal */ addFilters(filterModel, httpParams) { httpParams.filters = filterModel; } /** * Remettre manuellement les paramètres de query en cas d'initialState * @param params query params */ restoreInitialStateServer(params) { if (this.initialState.pagination?.page) { params.startRow = (this.initialState.pagination.page - 1) * this.pageSize; } if (this.initialState.filter?.filterModel) { params.filterModel = this.initialState.filter.filterModel; } if (this.initialState.sort?.sortModel) { params.sortModel = this.initialState.sort.sortModel; } } /** * Détection du changement de langue depuis le service i18n (display) * @param code */ onLangChange(code) { // si la langue n'est pas gérée (ni anglais ni francais), pas de traitement if (this.localeText && this.localeText !== 'fr' && this.localeText !== 'en') return; // sinon mis a jour en français ou anglais this.localeText = code === 'fr' ? AG_GRID_LOCALE_FR : undefined; } /** * Permettre d'afficher sur plusieurs lignes en mode serveur (equivalent autoHeight en mode client) * Calculer la dimension de chaque row par rapport à son contenu et recalculer la taille de la grille * globale (limitation ag-grid sur le mode infinite) */ setHeightOnRows() { if (!this.grid || !this.grid.nativeElement) return; let gridHeight = 0; const rows = this.grid.nativeElement.getElementsByClassName('ag-row'); this.agGrid.api.forEachNode((node, i) => { if (rows && rows[i]) { rows[i].style.setProperty('transform', 'translateY(' + gridHeight + 'px)'); const nodesCellValue = rows[i].getElementsByClassName('ag-cell-value'); // set new row height if (nodesCellValue) { let rowHeight = this.getMaxHeightOnRow(nodesCellValue) + 10; node.setRowHeight(rowHeight, false); node.rowTop = gridHeight; // increment grid height gridHeight += rowHeight; } } }); // update grid height let elements = this.grid.nativeElement.getElementsByClassName('ag-center-cols-viewport'); if (elements && elements[0]) { elements[0].style.height = `${gridHeight}px`; } } /** * Get max cell height needed on row * @param nodesCell each cells on row * @returns max height */ getMaxHeightOnRow(nodesCell) { const maxHeight = Array.from(nodesCell)?.reduce((a, b) => (a.clientHeight > b.clientHeight ? a : b)).clientHeight; // set min height of 30px if row height is not defined return maxHeight && maxHeight > 31 ? maxHeight : 31; } /** * Redéfinir le focus pour les cellules possédant des éléments interactifs (focusables, ex. buttons) * Suppression de la gestion du focus par défaut de ag grid lorsque c'est le cas */ suppressCellKeyboardEvent() { this.defaultColDef.suppressKeyboardEvent = (params) => { const e = params.event; return this.suppressDefaultKeyboardEvent(e, '.ag-cell'); }; } /** * Redéfinir le focus pour les cellules d'en-tête possédant des floatings filters avec éléments interactifs (focusables, ex. buttons) * Suppression de la gestion du focus par défaut de ag grid lorsque c'est le cas */ suppressHeaderKeyboardEvent() { this.defaultColDef.suppressHeaderKeyboardEvent = (params) => { const e = params.event; return this.suppressDefaultKeyboardEvent(e, '.ag-floating-cell'); }; } suppressDefaultKeyboardEvent(e, classToSearch) { if (e.code == 'Tab' || e.key == 'Tab') { // get interactive children of cell const target = e.target; const focusableChildrenOfParent = target ?.closest(classToSearch) ?.querySelectorAll('button, [href], :not(.ag-hidden) > input[tabindex]:not([tabindex="-1"], select, textarea, [tabindex]:not([tabindex="-1"])'); if (!focusableChildrenOfParent || focusableChildrenOfParent.length == 0 || (!e.shiftKey && target == focusableChildrenOfParent[focusableChildrenOfParent.length - 1]) || (e.shiftKey && target == focusableChildrenOfParent[0]) || (e.shiftKey && target.classList.contains('ag-cell'))) { return false; // if no interactive elements are present do not suppress } return true; // else suppress } return false; // do not suppress by default } /* Fix to force reload of ag-Grid data when no data is previously displayed (e.g., after applying a filter). The modelUpdated callback is not called the first time, and cacheBlockState remains in "no data" mode. ag-Grid bug on infite mode ? Inconvenience: Data is loaded twice in this case. */ forceReloadOnNoData() { const cacheBlock = this.agGrid.api.getCacheBlockState(); if ((!cacheBlock || Object.keys(cacheBlock).length === 0) && this.totalElements > 0) { this.agGrid.api.refreshInfiniteCache(); } } // fixme: refacto gestion de la pagination pour simplification initPagination() { this.initialPagination = this.initialState?.pagination?.page ? this.initialState.pagination.page : 0; this.pageSize = this.pageSize === undefined && this.initialState.pagination?.pageSize ? this.initialState.pagination?.pageSize : this.pageSize; this.gridOptions.paginationPageSize = this.pageSize; this.initialStatePagination = { rowsPerPage: this.pageSize, page: this.initialPagination === 0 ? 1 : this.initialPagination, // l'indexation de la pagination doit commencer à 1 ici sort: null, }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DsfrGridComponent, deps: [{ token: i1.DsfrI18nService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: DsfrGridComponent, selector: "dsfr-ext-ag-grid, dsfrx-ag-grid", inputs: { gridId: "gridId", columnDefs: "columnDefs", caption: "caption", pageSize: "pageSize", localeText: "localeText", mode: "mode", rowData: "rowData", defaultColDef: "defaultColDef", initialState: "initialState", customClass: "customClass", showLoadingOverlay: "showLoadingOverlay", loadingOverlayTemplate: "loadingOverlayTemplate", overlayNoRowsTemplate: "overlayNoRowsTemplate", idNoRowsTemplate: "idNoRowsTemplate", fixedHeight: "fixedHeight", autoRowsHeight: "autoRowsHeight", gridOptions: "gridOptions", showExportCsv: "showExportCsv", rowId: "rowId", showPagination: "showPagination", showFooterResult: "showFooterResult", pageSizes: "pageSizes", result: "result" }, outputs: { sortChanged: "sortChanged", gridReady: "gridReady", gridPreDestroyed: "gridPreDestroyed", filterChanged: "filterChanged", cellSelect: "cellSelect", rowSelect: "rowSelect", selectionChange: "selectionChange", dataChange: "dataChange", dataRender: "dataRender", dataFail: "dataFail", cellEditingStopped: "cellEditingStopped" }, providers: [{ provide: EduRemoteAgGridApi, useExisting: forwardRef(() => DsfrGridComponent) }], queries: [{ propertyName: "footerResultsTemplate", first: true, predicate: ["footerResultsTemplate"], descendants: true, static: true }, { propertyName: "footerActionsTemplate", first: true, predicate: ["footerActionsTemplate"], descendants: true, static: true }, { propertyName: "headerActionsTemplate", first: true, predicate: ["headerActionsTemplate"], descendants: true, static: true }], viewQueries: [{ propertyName: "grid", first: true, predicate: ["grid"], descendants: true, read: ElementRef }, { propertyName: "agGrid", first: true, predicate: AgGridAngular, descendants: true }], ngImport: i0, template: "<!-- AG Grid Angular Component -->\n<div\n class=\"edu-grid__wrapper fr-table\"\n [class]=\"customClass\"\n [ngClass]=\"{ 'dsfrx-auto-height__server': autoRowsHeight, 'fr-table--selectable': selectable }\">\n <!-- Header ------------------------------->\n <div class=\"fr-table__header\">\n <!-- Gestion du titre du tableau -->\n @if (caption) {\n <p [id]=\"captionId\" class=\"edu-grid__title\">\n {{ caption }}\n </p>\n } @else {\n <div [id]=\"captionId\" class=\"edu-grid__title\">\n <ng-content select=\"[caption]\"></ng-content>\n </div>\n }\n <!-- Template actions group\u00E9es -->\n @if (headerActionsTemplate) {\n <div class=\"edu-grid__actions\">\n <ng-container *ngTemplateOutlet=\"headerActionsTemplate\"></ng-container>\n </div>\n } @else if (showExportCsv) {\n <div class=\"edu-grid__actions\">\n <dsfr-button\n label=\"Exporter au format CSV\"\n customClass=\"edu-grid__actions--export\"\n (click)=\"onClickExportCsv()\"\n variant=\"secondary\"></dsfr-button>\n </div>\n }\n </div>\n\n <!-- Client side-->\n @if (mode === 'client') {\n <ag-grid-angular\n [rowData]=\"rowData\"\n #grid\n style=\"width: 100%\"\n class=\"ag-theme-alpine\"\n [id]=\"gridId\"\n [ngStyle]=\"{ height: fixedHeight ? fixedHeight : '100%' }\"\n [ngClass]=\"customClass\"\n [columnDefs]=\"columnDefs\"\n [defaultColDef]=\"defaultColDef\"\n [initialState]=\"initialState\"\n [gridOptions]=\"gridOptions\"\n [loading]=\"loading\"\n [overlayLoadingTemplate]=\"loadingOverlayTemplate\"\n [overlayNoRowsTemplate]=\"overlayNoRowsTemplate\"\n [suppressPaginationPanel]=\"true\"\n [localeText]=\"localeText\"\n [animateRows]=\"false\"\n (columnResized)=\"onColumnResized()\"\n (gridSizeChanged)=\"onGridSizeChanged($event)\"\n (modelUpdated)=\"onModelUpdated($event)\"\n (cellClicked)=\"onCellClicked($event)\"\n (cellEditingStopped)=\"onCellEditingStop($event)\"\n (filterChanged)=\"onFilterChange($event)\"\n (sortChanged)=\"onSortChange($event)\"\n (rowSelected)=\"onRowSelected($event)\"\n (selectionChanged)=\"onSelectionChanged($event)\"\n (gridReady)=\"onGridReady($event)\"></ag-grid-angular>\n } @else if (mode === 'server') {\n <!-- Remote data-->\n <ag-grid-angular\n remoteAgGridBinding\n #grid\n style=\"width: 100%\"\n class=\"ag-theme-alpine\"\n [id]=\"gridId\"\n [ngStyle]=\"{ height: fixedHeight ? fixedHeight : '100%' }\"\n [ngClass]=\"customClass\"\n [columnDefs]=\"columnDefs\"\n [defaultColDef]=\"defaultColDef\"\n [initialState]=\"initialState\"\n [gridOptions]=\"gridOptions\"\n [loading]=\"loading\"\n [overlayLoadingTemplate]=\"loadingOverlayTemplate\"\n [overlayNoRowsTemplate]=\"overlayNoRowsTemplate\"\n [suppressPaginationPanel]=\"true\"\n [localeText]=\"localeText\"\n [animateRows]=\"false\"\n (columnResized)=\"onColumnResized()\"\n (firstDataRendered)=\"onFirstDataRendered()\"\n (gridSizeChanged)=\"onGridSizeChanged($event)\"\n (modelUpdated)=\"onModelUpdated($event)\"\n (cellClicked)=\"onCellClicked($event)\"\n (cellEditingStopped)=\"onCellEditingStop($event)\"\n (filterChanged)=\"onFilterChange($event)\"\n (sortChanged)=\"onSortChange($event)\"\n (rowSelected)=\"onRowSelected($event)\"\n (selectionChanged)=\"onSelectionChanged($event)\"\n (gridReady)=\"onGridReady($event)\"></ag-grid-angular>\n }\n\n <!-- Footer -->\n @if (totalElements > 0 && !isLoadingServerSide) {\n <dsfr-table-footer\n [initialState]=\"initialStatePagination\"\n [rowsPerPageOptions]=\"pageSizes\"\n [showFooterResult]=\"showFooterResult\"\n [showPagination]=\"showPagination\"\n [currentPage]=\"currentPage\"\n [footerActionsTemplate]=\"footerActionsTemplate\"\n [footerResultsTemplate]=\"footerResultsTemplate\"\n [totalPage]=\"totalPage\"\n [totalElements]=\"totalElements\"\n (rowsPerPageChange)=\"onChangePageSize($event)\"\n (pageSelect)=\"onPage($event)\"\n data-testid=\"ag-grid-footer\"></dsfr-table-footer>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.ag-checkbox-input-wrapper input{opacity:1;background:transparent}.ag-checkbox-input-wrapper:before,.ag-checkbox-input-wrapper:after,.ag-checkbox-input-wrapper.ag-checked:after{content:none}.ag-checkbox-input:before{--data-uri-svg: none;height:1rem;width:1rem;background-image:radial-gradient(at 5px 4px,transparent 4px,var(--border-active-blue-france) 4px,var(--border-active-blue-france) 5px,transparent 6px),linear-gradient(var(--border-active-blue-france),var(--border-active-blue-france)),radial-gradient(at calc(100% - 5px) 4px,transparent 4px,var(--border-active-blue-france) 4px,var(--border-active-blue-france) 5px,transparent 6px),linear-gradient(var(--border-active-blue-france),var(--border-active-blue-france)),radial-gradient(at calc(100% - 5px) calc(100% - 4px),transparent 4px,var(--border-active-blue-france) 4px,var(--border-active-blue-france) 5px,transparent 6px),linear-gradient(var(--border-active-blue-france),var(--border-active-blue-france)),radial-gradient(at 5px calc(100% - 4px),transparent 4px,var(--border-active-blue-france) 4px,var(--border-active-blue-france) 5px,transparent 6px),linear-gradient(var(--border-active-blue-france),var(--border-active-blue-france)),var(--data-uri-svg);background-position:0 0,.25rem 0,100% 0,0 .25rem,100% 100%,calc(100% - .25rem) 100%,0 100%,100% .25rem,50%;background-repeat:no-repeat;background-size:.25rem .25rem,calc(100% - .25rem) 1px,.25rem .25rem,1px calc(100% - .5rem),.25rem .25rem,calc(100% - .5rem) 1px,.25rem .25rem,1px calc(100% - .5rem),1rem;border-radius:.25rem;content:\"\";position:absolute}.ag-checkbox-input-wrapper.ag-indeterminate:after{color:var(--background-active-blue-france)}.ag-checked .ag-checkbox-input:before{background-color:var(--background-active-blue-france);--data-uri-svg: url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23f5f5fe' d='m10 15.17 9.2-9.2 1.4 1.42L10 18l-6.36-6.36 1.4-1.42z'/%3E%3C/svg%3E\")}:root[data-fr-theme=dark] .ag-checked .ag-checkbox-input:before,.ag-theme-alpine-dark .ag-checked .ag-checkbox-input:before{--data-uri-svg: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill='%23161616' d='M10 15.17l9.2-9.2 1.4 1.42L10 18l-6.36-6.36 1.4-1.42z'/></svg>\")}.edu-grid__wrapper{width:100%}.edu-grid__wrapper .fr-pagination{margin-top:1rem}.edu-grid__wrapper .no-data{text-align:center;font-style:italic}.edu-grid__wrapper .edu-grid__title{font-size:1.5rem;margin-bottom:1rem;line-height:2rem}.fr-table__header .edu-grid__actions{display:flex;align-items:center}.fr-table__header .edu-grid__actions .fr-btns-group{padding:0}.fr-table__header .edu-grid__actions--export{margin-bottom:1rem;margin-left:.5rem}.ag-theme-alpine,.ag-theme-alpine-dark{--border-contrast-grey: var(--grey-625-425);--ag-data-color: var(--text-default-grey);--ag-menu-border-color: var(--border-contrast-grey);--ag-row-hover-color: (var(--background-alt-grey-hover));--ag-input-focus-border-color: #0a76f6;--ag-background-color: var(--background-default-grey);--ag-header-foreground-color: var(--text-default-grey);--ag-column-hover-color: var(--background-alt-grey-hover);--ag-alpine-active-color: var(--text-default-grey);--ag-foreground-color: var(--text-default-grey);--ag-secondary-foreground-color: var(--ag-foreground-color);--ag-disabled-foreground-color: var(--text-disabled-grey);--ag-border-color: var(--border-contrast-grey);--ag-secondary-border-color: #dde2eb;--ag-header-background-color: var(--background-alt-grey);--ag-tooltip-background-color: var(--background-alt-grey);--ag-odd-row-background-color: var(--background-default-grey);--ag-control-panel-background-color: var(--background-alt-grey);--ag-subheader-background-color: var(--background-default-grey) --ag-invalid-color: var(--text-default-error);--ag-checkbox-background-color: var(--ag-background-color);--ag-checkbox-checked-color: var(--background-active-blue-france);--ag-checkbox-border-radius: .25rem;--ag-input-disabled-border-color: var(--background-disabled-grey);--ag-input-disabled-background-color: var(--background-disabled-grey);--ag-borders: none;--ag-borders-critical: 1px solid;--ag-borders-input: 1px solid;--ag-input-border-color: var(--ag-border-color);--ag-input-border-color-invalid: var(--ag-invalid-color);--ag-input-focus-box-shadow: none;--ag-selected-row-background-color: transparent;--ag-border-radius: 0;--ag-grid-size: 8px;--ag-icon-size: 1rem;--ag-header-height: calc(var(--ag-grid-size) * 6);--ag-header-column-separator-color: var(--ag-row-border-color);--ag-row-height: calc(var(--ag-grid-size) * 5.45);--ag-row-border-style: solid;--ag-row-border-width: 1px;--ag-row-border-color: var(--border-contrast-grey);--ag-header-column-separator-height: 120%;--ag-cell-horizontal-padding: calc(var(--ag-grid-size) * 2);--ag-cell-widget-spacing: calc(var(--ag-grid-size) * 1.5);--ag-font-family: \"Marianne\", arial, sans-serif;--ag-font-size: .875rem}.ag-theme-alpine [class^=fr-icon-]:before,.ag-theme-alpine [class^=fr-icon-]:after,.ag-theme-alpine-dark [class^=fr-icon-]:before,.ag-theme-alpine-dark [class^=fr-icon-]:after{--icon-size: 1rem}[class^=ag-theme-alpine] .ag-row{font-size:var(--ag-font-size)}[class^=ag-theme-alpine] .ag-menu{border:1px solid var(--ag-menu-border-color);border-radius:0}[class^=ag-theme-alpine] .ag-root-wrapper{border:1px solid var(--ag-border-color)}[class^=ag-theme-alpine] .ag-sticky-bottom,[class^=ag-theme-alpine] .ag-row:last-child{border-bottom:none}[class^=ag-theme-alpine] .ag-header{font-size:.875rem;background-size:100% 1px;background-position:bottom;background-repeat:no-repeat;background-color:var(--background-alt-grey);background-image:linear-gradient(0deg,var(--border-plain-grey),var(--border-plain-grey)),linear-gradient(0deg,var(--border-contrast-grey),var(--border-contrast-grey));color:var(--text-title-grey);border-bottom:none}[class^=ag-theme-alpine] .ag-header .ag-sort-indicator-icon{border:1px solid var(--border-default-grey);padding:.25rem;margin-left:var(--ag-grid-size);color:var(--text-action-high-blue-france);padding-left:6px}[class^=ag-theme-alpine] .ag-header .ag-sort-indicator-icon.ag-sort-order{padding-left:var(--ag-grid-size);border-right:none}[class^=ag-theme-alpine] .ag-header .ag-sort-indicator-icon.ag-sort-ascending-icon,[class^=ag-theme-alpine] .ag-header .ag-sort-indicator-icon.ag-sort-descending-icon{margin-left:0;border-left:none}[class^=ag-theme-alpine] .ag-header .ag-sort-indicator-icon.ag-sort-none-icon{padding-top:6px;min-height:32px}[class^=ag-theme-alpine] .ag-header .ag-sort-indicator-icon:hover{background-color:var(--background-contrast-grey)}[class^=ag-theme-alpine] .ag-header .ag-sort-indicator-container:has(.ag-sort-order.ag-hidden) .ag-sort-indicator-icon{margin-left:var(--ag-grid-size);border:1px solid var(--border-default-grey);min-width:32px}[class^=ag-theme-alpine] .ag-row,[class^=ag-theme-alpine] .ag-row-focus,[class^=ag-theme-alpine] .ag-cell-focus,[class^=ag-theme-alpine] .ag-cell{-moz-user-select:auto;-webkit-user-select:auto;-ms-user-select:auto;user-select:auto}[class^=ag-theme-alpine] .ag-ltr .ag-cell-focus:not(.ag-cell-range-selected):focus-within,[class^=ag-theme-alpine] .ag-ltr .ag-cell-focus:not(.ag-cell-range-selected):focus-visible{outline-style:solid;outline-color:#0a76f6;outline-offset:-2px;outline-width:2px}[class^=ag-theme-alpine] .ag-ltr .ag-cell-focus:not(.ag-cell-range-selected):focus-within:not(:focus-visible){outline-offset:-1px;outline-width:1px}[class^=ag-theme-alpine] .ag-floating-filter-full-body{padding:.25rem}[class^=ag-theme-alpine] input[class^=ag-][type=text],[class^=ag-theme-alpine] input[class^=ag-][type=date]{border:0;background-color:var(--background-contrast-grey);border-radius:.25rem .25rem 0 0;box-shadow:inset 0 -2px 0 0 var(--border-plain-grey);color:var(--text-default-grey);display:block;line-height:1.5rem;padding:.5rem 1rem}[class^=ag-theme-alpine] .ag-header-icon.ag-header-cell-filter-button.ag-filter-active .fr-icon-filter-line{position:relative}[class^=ag-theme-alpine] .ag-header-icon.ag-header-cell-filter-button.ag-filter-active .fr-icon-filter-line:after{content:\"\";width:.25rem;height:.25rem;position:absolute;top:2px;left:.5rem;transform:translate(100%,-100%);mask-image:unset;border-radius:50%}[class^=ag-theme-alpine] .ag-ltr .ag-floating-filter-button{margin-left:var(--ag-grid-size)}[class^=ag-theme-alpine] .ag-floating-filter-button .ag-button{font-size:1rem;line-height:1.5rem;min-height:2rem;background-color:transparent;color:var(--text-action-high-blue-france);box-shadow:inset 0 0 0 1px var(--border-default-grey);padding:.25rem .5rem;width:auto}[class^=ag-theme-alpine] .ag-floating-filter-button .ag-button:hover{background-color:var(--background-alt-grey-hover)}[class^=ag-theme-alpine] .ag-floating-filter-full-body{display:block;height:auto}[class^=ag-theme-alpine] .ag-floating-filter-full-body .fr-label+.fr-select{margin-top:0}[class^=ag-theme-alpine] .ag-advanced-filter-header-cell:focus-visible:after,[class^=ag-theme-alpine] .ag-header-cell:focus-visible:after,[class^=ag-theme-alpine] .ag-header-group-cell:focus-visible:after{border-color:#0a76f6}[class^=ag-theme-alpine] input[class^=ag-]:focus,[class^=ag-theme-alpine] .ag-select .ag-picker-field-wrapper:focus,[class^=ag-theme-alpine] .fr-select:focus{outline-style:solid;outline-color:#0a76f6;outline-offset:2px;outline-width:2px}[class^=ag-theme-alpine] input[type=checkbox][class^=ag-]:focus{outline:0}[class^=ag-theme-alpine] .ag-button:focus{outline-style:solid;outline-color:#0a76f6;outline-width:2px;outline-offset:0}[class^=ag-theme-alpine] .ag-select .ag-picker-field-wrapper{border-radius:.25rem .25rem 0 0;background-repeat:no-repeat;background-position:calc(100% - .5rem) 50%;background-size:1.5rem 1.5rem;border:none;margin-bottom:.25rem;background-color:var(--background-alt-raised-grey-hover);box-shadow:inset 0 -2px 0 0 var(--border-plain-grey);--data-uri-svg: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' x='0px' y='0px' viewBox='0 0 24 24' ><path fill='%23161616' d='M12,13.1l5-4.9l1.4,1.4L12,15.9L5.6,9.5l1.4-1.4L12,13.1z'/></svg>\");background-image:var(--data-uri-svg)}[class^=ag-theme-alpine] .ag-select .ag-picker-field-wrapper .ag-icon{display:none}.fr-table--selectable .ag-ltr .ag-column-first.ag-cell:has(.ag-selection-checkbox){background-color:var(--background-alt-grey);border-right:1px solid gray}.fr-table--selectable .ag-row-selected{border-top:1px solid var(--border-action-high-blue-france);border-bottom:1px solid var(--border-action-high-blue-france)}.fr-table--selectable .ag-row-selected .ag-column-first.ag-cell{border-left:1px solid var(--border-action-high-blue-france)}.fr-table--selectable .ag-row-selected .ag-column-last.ag-cell{border-right:1px solid var(--border-action-high-blue-france)}.fr-table--selectable .ag-row[aria-selected=true]+.ag-row[aria-selected=true]{border-top:none;border-bottom:1px solid gray}.fr-table--selectable .ag-row[aria-selected=true]:has(+.ag-row[aria-selected=false]){border-bottom:1px solid var(--border-action-high-blue-france)}.fr-table--selectable .ag-row[aria-selected=false]:has(+.ag-row[aria-selected=true]){border-bottom:1px solid var(--border-action-high-blue-france)}.fr-table--selectable .ag-row-selected+.ag-row:not([aria-selected=true]){border-top:1px solid var(--border-action-high-blue-france)}.fr-table--selectable .ag-row:not([aria-selected=true])+.ag-row-selected{border-bottom:1px solid gray}.fr-table--selectable .ag-row-selected:first-of-type{border-bottom:1px solid gray}.fr-table--selectable .ag-row[aria-selected=true]+.ag-row[aria-selected=true]:last-of-type,.fr-table--selectable .ag-row[aria-selected=true]:last-of-type{border-bottom:1px solid var(--border-action-high-blue-france)}.fr-table [class^=ag-theme-alpine] .ag-cell{border-bottom:none;border-top:none}.fr-table-bordered [class^=ag-theme-alpine],.fr-table--bordered [class^=ag-theme-alpine]{--ag-cell-horizontal-border: var(--ag-row-border-width) var(--ag-row-border-style) var(--ag-row-border-color);--ag-header-column-separator-display: block}.fr-table-bordered [class^=ag-theme-alpine] .ag-root-wrapper,.fr-table--bordered [class^=ag-theme-alpine] .ag-root-wrapper{border-right:none}.fr-table--striped [class^=ag-theme-alpine]{--ag-odd-row-background-color: var(--background-alt-grey)}:root[data-fr-theme=dark] .ag-select .ag-picker-field-wrapper{--data-uri-svg: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' x='0px' y='0px' viewBox='0 0 24 24' ><path fill='%23fff' d='M12,13.1l5-4.9l1.4,1.4L12,15.9L5.6,9.5l1.4-1.4L12,13.1z'/></svg>\")}.dsfrx-auto-height__server .ag-cell-value{word-break:break-word}.dsfrx-auto-height__server .ag-cell{display:flex;line-height:inherit}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i1.DsfrButtonComponent, selector: "dsfr-button", inputs: ["label", "type", "tooltipMessage", "variant", "buttonSize", "icon", "iconPosition", "disabled", "uppercase", "loader", "ariaLabel", "invertedOutlineContrast", "id", "buttonId", "ariaControls", "ariaPressed", "ariaHasPopup", "ariaExpanded", "tabIndex", "customClass", "buttonRole", "labelSrOnly", "size"] }, { kind: "component", type: i3.AgGridAngular, selector: "ag-grid-angular", inputs: ["gridOptions", "modules", "statusBar", "sideBar", "suppressContextMenu", "preventDefaultOnContextMenu", "allowContextMenuWithControlKey", "columnMenu", "suppressMenuHide", "enableBrowserTooltips", "tooltipTrigger", "tooltipShowDelay", "tooltipHideDelay", "tooltipMouseTrack", "tooltipShowMode", "tooltipInteraction", "popupParent", "copyHeadersToClipboard", "copyGroupHeadersToClipboard", "clipboardDelimiter", "suppressCopyRowsToClipboard", "suppressCopySingleCellRanges", "suppressLastEmptyLineOnPaste", "suppressClipboardPaste", "suppressClipboardApi", "suppressCutToClipboard", "columnDefs", "defaultColDef", "defaultColGroupDef", "columnTypes", "dataTypeDefinitions", "maintainColumnOrder", "enableStrictPivotColumnOrder", "suppressFieldDotNotation", "headerHeight", "groupHeaderHeight", "floatingFiltersHeight", "pivotHeaderHeight", "pivotGroupHeaderHeight", "allowDragFromColumnsToolPanel", "suppressMovableColumns", "suppressColumnMoveAnimation", "suppressMoveWhenColumnDragging", "suppressDragLeaveHidesColumns", "suppressRowGroupHidesColumns", "colResizeDefault", "suppressAutoSize", "autoSizePadding", "skipHeaderOnAutoSize", "autoSizeStrategy", "components", "editType", "singleClickEdit", "suppressClickEdit", "readOnlyEdit", "stopEditingWhenCellsLoseFocus", "enterNavigatesVertically", "enterNavigatesVerticallyAfterEdit", "enableCellEditingOnBackspace", "undoRedoCellEditing", "undoRedoCellEditingLimit", "defaultCsvExportParams", "suppressCsvExport", "defaultExcelExportParams", "suppressExcelExport", "excelStyles", "quickFilterText", "cacheQuickFilter", "includeHiddenColumnsInQuickFilter", "quickFilterParser", "quickFilterMatcher", "applyQuickFilterBeforePivotOrAgg", "excludeChildrenWhenTreeDataFiltering", "enableAdvancedFilter", "advancedFilterModel", "includeHiddenColumnsInAdvancedFilter", "advancedFilterParent", "advancedFilterBuilderParams", "suppressAdvancedFilterEval", "suppressSetFilterByDefault", "enableCharts", "chartThemes", "customChartThemes", "chartThemeOverrides", "chartToolPanelsDef", "chartMenuItems", "loadingCellRenderer", "loadingCellRendererParams", "loadingCellRendererSelector", "localeText", "masterDetail", "keepDetailRows", "keepDetailRowsCount", "detailCellRenderer", "detailCellRendererParams", "detailRowHeight", "detailRowAutoHeight", "context", "dragAndDropImageComponent", "dragAndDropImageComponentParams", "alignedGrids", "tabIndex", "rowBuffer", "valueCache", "valueCacheNeverExpires", "enableCellExpressions", "suppressTouch", "suppressFocusAfterRefresh", "suppressAsyncEvents", "suppressBrowserResizeObserver", "suppressPropertyNamesCheck", "suppressChangeDetection", "debug", "loading", "overlayLoadingTemplate", "loadingOverlayComponent", "loadingOverlayComponentParams", "suppressLoadingOverlay", "overlayNoRowsTemplate", "noRowsOverlayComponent", "noRowsOverlayComponentParams", "suppressNoRowsOverlay", "pagination", "paginationPageSize", "paginationPageSizeSelector", "paginationAutoPageSize", "paginateChildRows", "suppressPaginationPanel", "pivotMode", "pivotPanelShow", "pivotMaxGeneratedColumns", "pivotDefaultExpanded", "pivotColumnGroupTotals", "pivotRowTotals", "pivotSuppressAutoColumn", "suppressExpandablePivotGroups", "functionsReadOnly", "aggFuncs", "suppressAggFuncInHeader", "alwaysAggregateAtRootLevel", "aggregateOnlyChangedColumns", "suppressAggFilteredOnly", "removePivotHeaderRowWhenSingleValueColumn", "animateRows", "enableCellChangeFlash", "cellFlashDuration", "cellFlashDelay", "cellFadeDuration", "cellFadeDelay", "allowShowChangeAfterFilter", "domLayout", "ensureDomOrder", "enableRtl", "suppressColumnVirtualisation", "suppressMaxRenderedRowRestriction", "suppressRowVirtualisation", "rowDragManaged", "suppressRowDrag", "suppressMoveWhenRowDragging", "rowDragEntireRow", "rowDragMultiRow", "rowDragText", "fullWidthCellRenderer", "fullWidthCellRendererParams", "embedFullWidthRows", "suppressGroupMaintainValueType", "groupDisplayType", "groupDefaultExpanded", "autoGroupColumnDef", "groupMaintainOrder", "groupSelectsChildren", "groupLockGroupColumns", "groupAggFiltering", "groupIncludeFooter", "groupIncludeTotalFooter", "groupTotalRow", "grandTotalRow", "suppressStickyTotalRow", "groupSuppressBlankHeader", "groupSelectsFiltered", "showOpenedGroup", "groupRemoveSingleChildren", "groupRemoveLowestSingleChildren", "groupHideOpenParents", "groupAllowUnbalanced", "rowGroupPanelShow", "groupRowRenderer", "groupRowRendererParams", "suppressMakeColumnVisibleAfterUnGroup", "treeData", "rowGroupPanelSuppressSort", "suppressGroupRowsSticky", "pinnedTopRowData", "pinnedBottomRowData", "rowModelType", "rowData", "asyncTransactionWaitMillis", "suppressModelUpdateAfterUpdateTransaction", "datasource", "cacheOverflowSize", "infiniteInitialRowCount", "serverSideInitialRowCount", "suppressServerSideInfiniteScroll", "suppressServerSideFullWidthLoadingRow", "cacheBlockSize", "maxBlocksInCache", "maxConcurrentDatasourceRequests", "blockLoadDebounceMillis", "purgeClosedRowNodes", "serverSideDatasource", "serverSideSortAllLevels", "serverSideEnableClientSideSort", "serverSideOnlyRefreshFilteredGroups", "serverSideSortOnServer", "serverSideFilterOnServer", "serverSidePivotResultFieldSeparator", "viewportDatasource", "viewportRowModelPageSize", "viewportRowModelBufferSize", "alwaysShowHorizontalScroll", "alwaysShowVerticalScroll", "debounceVerticalScrollbar", "suppressHorizontalScroll", "suppressScrollOnNewData", "suppressScrollWhenPopupsAreOpen", "suppressAnimationFrame", "suppressMiddleClickScrolls", "suppressPreventDefaultOnMouseWheel", "scrollbarWidth", "rowSelection", "cellSelection", "rowMultiSelectWithClick", "suppressRowDeselection", "suppressRowClickSelection", "suppressCellFocus", "suppressHeaderFocus", "selectionColumnDef", "suppressMultiRangeSelection", "enableCellTextSelection", "enableRangeSelection", "enableRangeHandle", "enableFillHandle", "fillHandleDirection", "suppressClearOnFillReduction", "sortingOrder", "accentedSort", "unSortIcon", "suppressMultiSort", "alwaysMultiSort", "multiSortKey", "suppressMaintainUnsortedOrder", "icons", "rowHeight", "rowStyle", "rowClass", "rowClassRules", "suppressRowHoverHighlight", "suppressRowTransform", "columnHoverHighlight", "gridId", "deltaSort", "treeDataDisplayType", "enableGroupEdit", "initialState", "theme", "loadThemeGoogleFonts", "getContextMenuItems", "getMainMenuItems", "postProcessPopup", "processUnpinnedColumns", "processCellForClipboard", "processHeaderForClipboard", "processGroupHeaderForClipboard", "processCellFromClipboard", "sendToClipboard", "processDataFromClipboard", "isExternalFilterPresent", "doesExternalFilterPass", "getChartToolbarItems", "createChartContainer", "focusGridInnerElement", "navigateToNextHeader", "tabToNextHeader", "navigateToNextCell", "tabToNextCell", "getLocaleText", "getDocument", "paginationNumberFormatter", "getGroupRowAgg", "isGroupOpenByDefault", "initialGroupOrderComparator", "processPivotResultColDef", "processPivotResultColGroupDef", "getDataPath", "getChildCount", "getServerSideGroupLevelParams", "isServerSideGroupOpenByDefault", "isApplyServerSideTransaction", "isServerSideGroup", "getServerSideGroupKey", "getBusinessKeyForNode", "getRowId", "resetRowDataOnUpdate", "processRowPostCreate", "isRowSelectable", "isRowMaster", "fillOperation", "postSortRows", "getRowStyle", "getRowClass", "getRowHeight", "isFullWidthRow"], outputs: ["toolPanelVisibleChanged", "toolPanelSizeChanged", "columnMenuVisibleChanged", "contextMenuVisibleChanged", "cutStart", "cutEnd", "pasteStart", "pasteEnd", "columnVisible", "columnPinned", "columnResized", "columnMoved", "columnValueChanged", "columnPivotModeChanged", "columnPivotChanged", "columnGroupOpened", "newColumnsLoaded", "gridColumnsChanged", "displayedColumnsChanged", "virtualColumnsChanged", "columnEverythingChanged", "columnHeaderMouseOver", "columnHeaderMouseLeave", "columnHeaderClicked", "columnHeaderContextMenu", "componentStateChanged", "cellValueChanged", "cellEditRequest", "rowValueChanged", "cellEditingStarted", "cellEditingStopped", "rowEditingStarted", "rowEditingStopped", "undoStarted", "undoEnded", "redoStarted", "redoEnded", "cellSelectionDeleteStart", "cellSelectionDeleteEnd", "rangeDeleteStart", "rangeDeleteEnd", "fillStart", "fillEnd", "filterOpened", "filterChanged", "filterModified