UNPKG

@asif-dev/ng-pivottable

Version:

Angular wrappers for react-pivottable (PivotTable and PivotTableUI) — React 17

294 lines (288 loc) 13.6 kB
import * as i0 from '@angular/core'; import { inject, NgZone, PLATFORM_ID, Component, ChangeDetectionStrategy, Input, ViewChild, EventEmitter, ChangeDetectorRef, Output } from '@angular/core'; import { isPlatformBrowser } from '@angular/common'; import * as React from 'react'; import * as ReactDOM from 'react-dom'; import PivotTable from 'react-pivottable/PivotTable'; import PivotTableUI from 'react-pivottable/PivotTableUI'; // projects/angular-pivottable/src/lib/pivot-table/pivot-table.component.ts class NgPivotTableComponent { constructor() { this.data = []; this.rows = []; this.cols = []; this.vals = []; this.aggregatorName = 'Count'; this.ngZone = inject(NgZone); this.platformId = inject(PLATFORM_ID); this.isInitialized = false; this.isBrowser = isPlatformBrowser(this.platformId); } ngAfterViewInit() { if (this.isBrowser && this.containerRef?.nativeElement) { this.isInitialized = true; this.renderReact(); } } ngOnChanges(changes) { // Only re-render if component is initialized and we're in browser if (this.isInitialized && this.isBrowser) { this.renderReact(); } } renderReact() { if (!this.containerRef?.nativeElement) { return; } // Run React rendering outside Angular's zone to prevent unnecessary change detection this.ngZone.runOutsideAngular(() => { try { const props = { data: this.data || [], rows: this.rows || [], cols: this.cols || [], vals: this.vals || [], aggregatorName: this.aggregatorName || 'Count', rendererName: this.rendererName, valueFilter: this.valueFilter, sorters: this.sorters, derivedAttributes: this.derivedAttributes, hiddenAttributes: this.hiddenAttributes, hiddenFromAggregators: this.hiddenFromAggregators, hiddenFromDragDrop: this.hiddenFromDragDrop, menuLimit: this.menuLimit, unusedOrientationCutoff: this.unusedOrientationCutoff }; // Remove undefined properties Object.keys(props).forEach(key => { if (props[key] === undefined) { delete props[key]; } }); ReactDOM.render(React.createElement(PivotTable, props), this.containerRef.nativeElement); } catch (error) { console.error('Error rendering PivotTable:', error); } }); } ngOnDestroy() { if (this.isBrowser && this.containerRef?.nativeElement) { try { ReactDOM.unmountComponentAtNode(this.containerRef.nativeElement); } catch (error) { console.error('Error unmounting PivotTable:', error); } } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgPivotTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: NgPivotTableComponent, isStandalone: true, selector: "ng-pivot-table", inputs: { data: "data", rows: "rows", cols: "cols", vals: "vals", aggregatorName: "aggregatorName", rendererName: "rendererName", valueFilter: "valueFilter", sorters: "sorters", derivedAttributes: "derivedAttributes", hiddenAttributes: "hiddenAttributes", hiddenFromAggregators: "hiddenFromAggregators", hiddenFromDragDrop: "hiddenFromDragDrop", menuLimit: "menuLimit", unusedOrientationCutoff: "unusedOrientationCutoff" }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: `<div #container class="ng-pivottable-root"></div>`, isInline: true, styles: [":host{display:block}.ng-pivottable-root{width:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgPivotTableComponent, decorators: [{ type: Component, args: [{ selector: 'ng-pivot-table', template: `<div #container class="ng-pivottable-root"></div>`, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, styles: [":host{display:block}.ng-pivottable-root{width:100%}\n"] }] }], ctorParameters: () => [], propDecorators: { data: [{ type: Input }], rows: [{ type: Input }], cols: [{ type: Input }], vals: [{ type: Input }], aggregatorName: [{ type: Input }], rendererName: [{ type: Input }], valueFilter: [{ type: Input }], sorters: [{ type: Input }], derivedAttributes: [{ type: Input }], hiddenAttributes: [{ type: Input }], hiddenFromAggregators: [{ type: Input }], hiddenFromDragDrop: [{ type: Input }], menuLimit: [{ type: Input }], unusedOrientationCutoff: [{ type: Input }], containerRef: [{ type: ViewChild, args: ['container', { static: true }] }] } }); // projects/angular-pivottable/src/lib/pivot-table-ui/pivot-table-ui.component.ts class NgPivotTableUiComponent { constructor() { this.data = []; this.rows = []; this.cols = []; this.vals = []; this.aggregatorName = 'Count'; this.configChange = new EventEmitter(); this.stateChange = new EventEmitter(); this.ngZone = inject(NgZone); this.cdr = inject(ChangeDetectorRef); this.platformId = inject(PLATFORM_ID); this.isInitialized = false; this.internalState = {}; this.shouldUpdateFromInputs = true; this.isBrowser = isPlatformBrowser(this.platformId); } ngAfterViewInit() { if (this.isBrowser && this.containerRef?.nativeElement) { this.isInitialized = true; this.initializeInternalState(); this.renderReact(); } } ngOnChanges(changes) { if (this.isInitialized && this.isBrowser && this.shouldUpdateFromInputs) { // Only update internal state from inputs if we're not in the middle of a React onChange const hasRelevantChanges = Object.keys(changes).some(key => key !== 'data' || changes[key].currentValue !== changes[key].previousValue); if (hasRelevantChanges) { this.initializeInternalState(); this.renderReact(); } } } initializeInternalState() { // Initialize internal state from inputs this.internalState = { data: this.data || [], rows: this.rows || [], cols: this.cols || [], vals: this.vals || [], aggregatorName: this.aggregatorName || 'Count', rendererName: this.rendererName, valueFilter: this.valueFilter, sorters: this.sorters, derivedAttributes: this.derivedAttributes, hiddenAttributes: this.hiddenAttributes, hiddenFromAggregators: this.hiddenFromAggregators, hiddenFromDragDrop: this.hiddenFromDragDrop, menuLimit: this.menuLimit, unusedOrientationCutoff: this.unusedOrientationCutoff }; // Remove undefined properties Object.keys(this.internalState).forEach(key => { if (this.internalState[key] === undefined) { delete this.internalState[key]; } }); } renderReact() { if (!this.containerRef?.nativeElement) { return; } // Run React rendering outside Angular's zone this.ngZone.runOutsideAngular(() => { try { const props = { ...this.internalState, onChange: (newState) => { // Prevent input changes from overriding React's state during onChange this.shouldUpdateFromInputs = false; // Update internal state this.internalState = { ...newState }; // Run emissions inside Angular zone to trigger change detection if needed this.ngZone.run(() => { this.configChange.emit({ ...newState }); this.stateChange.emit({ ...newState }); // Mark for check in case parent component needs to update this.cdr.markForCheck(); }); // Re-render with new state this.renderReact(); // Re-enable input updates after a microtask Promise.resolve().then(() => { this.shouldUpdateFromInputs = true; }); } }; ReactDOM.render(React.createElement(PivotTableUI, props), this.containerRef.nativeElement); } catch (error) { console.error('Error rendering PivotTableUI:', error); } }); } /** * Programmatically update the pivot table state * @param state - Partial state to merge with current state */ updateState(state) { this.internalState = { ...this.internalState, ...state }; if (this.isInitialized) { this.renderReact(); } } /** * Get the current pivot table state */ getState() { return { ...this.internalState }; } ngOnDestroy() { if (this.isBrowser && this.containerRef?.nativeElement) { try { ReactDOM.unmountComponentAtNode(this.containerRef.nativeElement); } catch (error) { console.error('Error unmounting PivotTableUI:', error); } } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgPivotTableUiComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: NgPivotTableUiComponent, isStandalone: true, selector: "ng-pivot-table-ui", inputs: { data: "data", rows: "rows", cols: "cols", vals: "vals", aggregatorName: "aggregatorName", rendererName: "rendererName", valueFilter: "valueFilter", sorters: "sorters", derivedAttributes: "derivedAttributes", hiddenAttributes: "hiddenAttributes", hiddenFromAggregators: "hiddenFromAggregators", hiddenFromDragDrop: "hiddenFromDragDrop", menuLimit: "menuLimit", unusedOrientationCutoff: "unusedOrientationCutoff" }, outputs: { configChange: "configChange", stateChange: "stateChange" }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: `<div #container class="ng-pivottable-ui-root"></div>`, isInline: true, styles: [":host{display:block}.ng-pivottable-ui-root{width:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgPivotTableUiComponent, decorators: [{ type: Component, args: [{ selector: 'ng-pivot-table-ui', template: `<div #container class="ng-pivottable-ui-root"></div>`, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, styles: [":host{display:block}.ng-pivottable-ui-root{width:100%}\n"] }] }], ctorParameters: () => [], propDecorators: { data: [{ type: Input }], rows: [{ type: Input }], cols: [{ type: Input }], vals: [{ type: Input }], aggregatorName: [{ type: Input }], rendererName: [{ type: Input }], valueFilter: [{ type: Input }], sorters: [{ type: Input }], derivedAttributes: [{ type: Input }], hiddenAttributes: [{ type: Input }], hiddenFromAggregators: [{ type: Input }], hiddenFromDragDrop: [{ type: Input }], menuLimit: [{ type: Input }], unusedOrientationCutoff: [{ type: Input }], configChange: [{ type: Output }], stateChange: [{ type: Output }], containerRef: [{ type: ViewChild, args: ['container', { static: true }] }] } }); /* * Public API Surface of angular-pivottable */ /** * Generated bundle index. Do not edit. */ export { NgPivotTableComponent, NgPivotTableUiComponent }; //# sourceMappingURL=angular-pivottable.mjs.map