@anglr/grid
Version:
Angular module displaying grid
417 lines • 21 kB
JavaScript
import { Component, ChangeDetectionStrategy, Inject, Optional, Type, Input, ContentChild, forwardRef, inject, ViewChild, ViewContainerRef, resolveForwardRef } from '@angular/core';
import { extend } from '@jscrpt/common/extend';
import { lastValueFrom } from '@jscrpt/common/rxjs';
import { BehaviorSubject, map, combineLatest, distinctUntilChanged, take } from 'rxjs';
import { CONTENT_RENDERER_TYPE, DATA_LOADER_TYPE, DEFAULT_OPTIONS, GRID_INITIALIZER_TYPE, GRID_INSTANCE, GRID_OPTIONS, GRID_PLUGIN_INSTANCES, METADATA_GATHERER, METADATA_SELECTOR_TYPE, NO_DATA_RENDERER_TYPE, ORDERING_TYPE, PAGING_TYPE, ROW_SELECTOR_TYPE } from '../../misc/tokens';
import { AsyncDataLoaderComponent, BasicPagingComponent, NoRowSelectorComponent, NoGridInitializerComponent, NoMetadataSelectorComponent, SimpleNoDataRendererComponent, SingleOrderingComponent, TableContentRendererComponent } from '../../plugins';
import { GridPluginType } from '../../misc/enums';
import { GridPluginInstancesDef } from '../../misc/gridPluginInstancesDef';
import * as i0 from "@angular/core";
/**
* Default 'GridOptions'
*/
const defaultOptions = {
autoInitialize: true,
plugins: {
contentRenderer: {
type: forwardRef(() => TableContentRendererComponent),
instance: null,
instanceCallback: null,
options: null,
},
dataLoader: {
type: forwardRef(() => AsyncDataLoaderComponent),
instance: null,
instanceCallback: null,
options: null,
},
gridInitializer: {
type: forwardRef(() => NoGridInitializerComponent),
instance: null,
instanceCallback: null,
options: null,
},
metadataSelector: {
type: forwardRef(() => NoMetadataSelectorComponent),
instance: null,
instanceCallback: null,
options: null,
},
noDataRenderer: {
type: forwardRef(() => SimpleNoDataRendererComponent),
instance: null,
instanceCallback: null,
options: null,
},
ordering: {
type: forwardRef(() => SingleOrderingComponent),
instance: null,
instanceCallback: null,
options: null,
},
paging: {
type: forwardRef(() => BasicPagingComponent),
instance: null,
instanceCallback: null,
options: null,
},
rowSelector: {
type: forwardRef(() => NoRowSelectorComponent),
instance: null,
instanceCallback: null,
options: null,
},
}
};
/**
* Grid component used for rendering grid
*/
export class GridComponent {
/**
* Metadata gatherer instance
*/
get metadataGatherer() {
return this.metadataGathererChild;
}
//######################### public properties - inputs #########################
/**
* @inheritdoc
*/
get gridOptions() {
return this.ɵgridOptions;
}
set gridOptions(options) {
this.ɵgridOptions = extend(true, this.ɵgridOptions, options);
}
//######################### public properties - implementation of Grid #########################
/**
* @inheritdoc
*/
get initialized() {
return this.initializedSubject.asObservable().pipe(distinctUntilChanged());
}
//######################### constructors #########################
constructor(options, pagingType, orderingType, gridInitializerType, dataLoaderType, contentRendererType, metadataSelectorType, noDataRendererType, rowSelectorType) {
//######################### protected fields #########################
/**
* Object storing current used plugin type
*/
this.pluginTypes = {
ContentRenderer: null,
DataLoader: null,
GridInitializer: null,
MetadataSelector: null,
NoDataRenderer: null,
Ordering: null,
Paging: null,
RowSelector: null,
};
/**
* Grid plugin instances available for grid
*/
this.pluginInstances = inject(GRID_PLUGIN_INSTANCES);
/**
* Instance that allows changing state of initialized plugins
*/
this.pluginsOptionsInitialization = {
contentRenderer: new BehaviorSubject(false),
dataLoader: new BehaviorSubject(false),
gridInitializer: new BehaviorSubject(false),
metadataSelector: new BehaviorSubject(false),
noDataRenderer: new BehaviorSubject(false),
ordering: new BehaviorSubject(false),
paging: new BehaviorSubject(false),
rowSelector: new BehaviorSubject(false),
};
/**
* Subject used for indication that grid was initialized
*/
this.initializedSubject = new BehaviorSubject(false);
/**
* @inheritdoc
*/
this.pluginsOptionsInitialized = combineLatest([
this.pluginsOptionsInitialization.contentRenderer,
this.pluginsOptionsInitialization.dataLoader,
this.pluginsOptionsInitialization.gridInitializer,
this.pluginsOptionsInitialization.metadataSelector,
this.pluginsOptionsInitialization.noDataRenderer,
this.pluginsOptionsInitialization.ordering,
this.pluginsOptionsInitialization.paging,
this.pluginsOptionsInitialization.rowSelector,
]).pipe(map(initFlags => {
const [contentRenderer, dataLoader, gridInitializer, metadataSelector, noDataRenderer, ordering, paging, rowSelector] = initFlags;
return contentRenderer && dataLoader && gridInitializer && metadataSelector && noDataRenderer && ordering && paging && rowSelector;
}), distinctUntilChanged());
this.pluginsOptionsInitialized.subscribe(async (initialized) => {
if (initialized && this.ɵgridOptions.autoInitialize && !(await lastValueFrom(this.initialized.pipe(take(1))))) {
this.initialize(false);
}
});
const opts = extend({}, options);
if (!opts.plugins) {
opts.plugins = {};
}
if (pagingType) {
opts.plugins.paging ??= {};
opts.plugins.paging.type = pagingType;
}
if (orderingType) {
opts.plugins.ordering ??= {};
opts.plugins.ordering.type = orderingType;
}
if (gridInitializerType) {
opts.plugins.gridInitializer ??= {};
opts.plugins.gridInitializer.type = gridInitializerType;
}
if (dataLoaderType) {
opts.plugins.dataLoader ??= {};
opts.plugins.dataLoader.type = dataLoaderType;
}
if (contentRendererType) {
opts.plugins.contentRenderer ??= {};
opts.plugins.contentRenderer.type = contentRendererType;
}
if (metadataSelectorType) {
opts.plugins.metadataSelector ??= {};
opts.plugins.metadataSelector.type = metadataSelectorType;
}
if (noDataRendererType) {
opts.plugins.noDataRenderer ??= {};
opts.plugins.noDataRenderer.type = noDataRendererType;
}
if (rowSelectorType) {
opts.plugins.rowSelector ??= {};
opts.plugins.rowSelector.type = rowSelectorType;
}
this.ɵgridOptions = extend(true, {}, inject(DEFAULT_OPTIONS), opts);
}
//######################### public methods - implementation of OnInit #########################
/**
* Initialize component
*/
ngOnInit() {
if (this.gridOptions.autoInitialize) {
this.initOptions();
}
}
//######################### public methods - implementation of Grid #########################
/**
* @inheritdoc
*/
async initialize(force) {
this.initializedSubject.next(false);
await this.pluginInstances[GridPluginType.RowSelector].initialize(force);
await this.pluginInstances[GridPluginType.MetadataSelector].initialize(force);
await this.pluginInstances[GridPluginType.GridInitializer].initialize(force);
await this.pluginInstances[GridPluginType.Ordering].initialize(force);
await this.pluginInstances[GridPluginType.Paging].initialize(force);
await this.pluginInstances[GridPluginType.ContentRenderer].initialize(force);
await this.pluginInstances[GridPluginType.NoDataRenderer].initialize(force);
await this.pluginInstances[GridPluginType.DataLoader].initialize(force);
this.initializedSubject.next(true);
}
/**
* @inheritdoc
*/
async initOptions() {
const initOptionsFn = async (pluginType, pluginDescription, initOptionsSubject, pluginViewContainer, beforeOptionsSet) => {
if ((pluginDescription.instance && pluginDescription.type) || (!pluginDescription.instance && !pluginDescription.type)) {
throw new Error(`GridComponent: provide only instance or type for plugin ${pluginType}, cant provide both of these properties at the same time!`);
}
let newInstance = false;
initOptionsSubject.next(false);
//only for existing instances of plugins
if (pluginDescription.instance) {
this.pluginTypes[pluginType] = null;
pluginViewContainer.clear();
//plugin is different from current plugin
if (pluginDescription.instance != this.pluginInstances[pluginType]) {
this.pluginInstances[pluginType] = pluginDescription.instance;
pluginDescription.instance.gridPlugins = this.pluginInstances;
newInstance = true;
}
}
//only if plugin type is provided
else if (pluginDescription.type) {
const type = resolveForwardRef(pluginDescription.type);
//new type provided
if (type != this.pluginTypes[pluginType]) {
this.pluginTypes[pluginType] = type;
pluginViewContainer.clear();
const component = pluginViewContainer.createComponent(type);
component.changeDetectorRef.detectChanges();
this.pluginInstances[pluginType] = component.instance;
newInstance = true;
}
}
//only call when new instance of plugin was created
if (newInstance) {
await beforeOptionsSet?.(this.pluginInstances[pluginType]);
pluginDescription.instanceCallback?.(this.pluginInstances[pluginType]);
}
//options are available, set them
if (pluginDescription.options) {
this.pluginInstances[pluginType].options = pluginDescription.options;
}
await this.pluginInstances[pluginType].initOptions();
initOptionsSubject.next(true);
};
//init options paging
await initOptionsFn(GridPluginType.Paging, this.ɵgridOptions.plugins.paging, this.pluginsOptionsInitialization.paging, this.pagingContainer);
//init options ordering
await initOptionsFn(GridPluginType.Ordering, this.ɵgridOptions.plugins.ordering, this.pluginsOptionsInitialization.ordering, this.orderingContainer);
//init options grid initializer
await initOptionsFn(GridPluginType.GridInitializer, this.ɵgridOptions.plugins.gridInitializer, this.pluginsOptionsInitialization.gridInitializer, this.gridInitializerContainer);
//init options data loader
await initOptionsFn(GridPluginType.DataLoader, this.ɵgridOptions.plugins.dataLoader, this.pluginsOptionsInitialization.dataLoader, this.dataLoaderContainer);
//init options content renderer
await initOptionsFn(GridPluginType.ContentRenderer, this.ɵgridOptions.plugins.contentRenderer, this.pluginsOptionsInitialization.contentRenderer, this.contentRendererContainer);
//init options metadata selector
await initOptionsFn(GridPluginType.MetadataSelector, this.ɵgridOptions.plugins.metadataSelector, this.pluginsOptionsInitialization.metadataSelector, this.metadataSelectorContainer, metadataSelector => {
if (this.metadataGatherer) {
metadataSelector.setMetadataGatherer(this.metadataGatherer);
}
});
//init options no data renderer
await initOptionsFn(GridPluginType.NoDataRenderer, this.ɵgridOptions.plugins.noDataRenderer, this.pluginsOptionsInitialization.noDataRenderer, this.noDataRendererContainer);
//init options row selector
await initOptionsFn(GridPluginType.RowSelector, this.ɵgridOptions.plugins.rowSelector, this.pluginsOptionsInitialization.rowSelector, this.rowSelectorContainer);
}
/**
* @inheritdoc
*/
getPlugin(pluginId) {
return this.pluginInstances[pluginId];
}
/**
* @inheritdoc
*/
setGridPluginInstances(plugin) {
plugin.gridPlugins = this.pluginInstances;
}
/**
* @inheritdoc
*/
async execute(...actions) {
if (!actions) {
return;
}
for (const action of actions) {
await action(this);
}
}
/**
* @inheritdoc
*/
executeAndReturn(func) {
return func(this);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.0", ngImport: i0, type: GridComponent, deps: [{ token: GRID_OPTIONS, optional: true }, { token: PAGING_TYPE, optional: true }, { token: ORDERING_TYPE, optional: true }, { token: GRID_INITIALIZER_TYPE, optional: true }, { token: DATA_LOADER_TYPE, optional: true }, { token: CONTENT_RENDERER_TYPE, optional: true }, { token: METADATA_SELECTOR_TYPE, optional: true }, { token: NO_DATA_RENDERER_TYPE, optional: true }, { token: ROW_SELECTOR_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.0", type: GridComponent, isStandalone: true, selector: "ng-grid", inputs: { gridOptions: "gridOptions" }, providers: [
{
provide: GRID_INSTANCE,
useExisting: forwardRef(() => GridComponent),
},
{
provide: GRID_PLUGIN_INSTANCES,
useFactory: () => { return new GridPluginInstancesDef(); },
},
{
provide: DEFAULT_OPTIONS,
useValue: defaultOptions,
},
], queries: [{ propertyName: "metadataGathererChild", first: true, predicate: METADATA_GATHERER, descendants: true }], viewQueries: [{ propertyName: "metadataSelectorContainer", first: true, predicate: ["metadataSelectorContainer"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "dataLoaderContainer", first: true, predicate: ["dataLoaderContainer"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "rowSelectorContainer", first: true, predicate: ["rowSelectorContainer"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "gridInitializerContainer", first: true, predicate: ["gridInitializerContainer"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "orderingContainer", first: true, predicate: ["orderingContainer"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "contentRendererContainer", first: true, predicate: ["contentRendererContainer"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "noDataRendererContainer", first: true, predicate: ["noDataRendererContainer"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "pagingContainer", first: true, predicate: ["pagingContainer"], descendants: true, read: ViewContainerRef, static: true }], ngImport: i0, template: "<ng-container #metadataSelectorContainer/>\r\n<ng-container #dataLoaderContainer/>\r\n<ng-container #rowSelectorContainer/>\r\n<ng-container #gridInitializerContainer/>\r\n<ng-container #orderingContainer/>\r\n<ng-container #contentRendererContainer/>\r\n<ng-container #noDataRendererContainer/>\r\n<ng-container #pagingContainer/>", changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.0", ngImport: i0, type: GridComponent, decorators: [{
type: Component,
args: [{ selector: 'ng-grid', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
{
provide: GRID_INSTANCE,
useExisting: forwardRef(() => GridComponent),
},
{
provide: GRID_PLUGIN_INSTANCES,
useFactory: () => { return new GridPluginInstancesDef(); },
},
{
provide: DEFAULT_OPTIONS,
useValue: defaultOptions,
},
], template: "<ng-container #metadataSelectorContainer/>\r\n<ng-container #dataLoaderContainer/>\r\n<ng-container #rowSelectorContainer/>\r\n<ng-container #gridInitializerContainer/>\r\n<ng-container #orderingContainer/>\r\n<ng-container #contentRendererContainer/>\r\n<ng-container #noDataRendererContainer/>\r\n<ng-container #pagingContainer/>" }]
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [GRID_OPTIONS]
}, {
type: Optional
}] }, { type: i0.Type, decorators: [{
type: Inject,
args: [PAGING_TYPE]
}, {
type: Optional
}] }, { type: i0.Type, decorators: [{
type: Inject,
args: [ORDERING_TYPE]
}, {
type: Optional
}] }, { type: i0.Type, decorators: [{
type: Inject,
args: [GRID_INITIALIZER_TYPE]
}, {
type: Optional
}] }, { type: i0.Type, decorators: [{
type: Inject,
args: [DATA_LOADER_TYPE]
}, {
type: Optional
}] }, { type: i0.Type, decorators: [{
type: Inject,
args: [CONTENT_RENDERER_TYPE]
}, {
type: Optional
}] }, { type: i0.Type, decorators: [{
type: Inject,
args: [METADATA_SELECTOR_TYPE]
}, {
type: Optional
}] }, { type: i0.Type, decorators: [{
type: Inject,
args: [NO_DATA_RENDERER_TYPE]
}, {
type: Optional
}] }, { type: i0.Type, decorators: [{
type: Inject,
args: [ROW_SELECTOR_TYPE]
}, {
type: Optional
}] }], propDecorators: { gridOptions: [{
type: Input
}], metadataSelectorContainer: [{
type: ViewChild,
args: ['metadataSelectorContainer', { read: ViewContainerRef, static: true }]
}], dataLoaderContainer: [{
type: ViewChild,
args: ['dataLoaderContainer', { read: ViewContainerRef, static: true }]
}], rowSelectorContainer: [{
type: ViewChild,
args: ['rowSelectorContainer', { read: ViewContainerRef, static: true }]
}], gridInitializerContainer: [{
type: ViewChild,
args: ['gridInitializerContainer', { read: ViewContainerRef, static: true }]
}], orderingContainer: [{
type: ViewChild,
args: ['orderingContainer', { read: ViewContainerRef, static: true }]
}], contentRendererContainer: [{
type: ViewChild,
args: ['contentRendererContainer', { read: ViewContainerRef, static: true }]
}], noDataRendererContainer: [{
type: ViewChild,
args: ['noDataRendererContainer', { read: ViewContainerRef, static: true }]
}], pagingContainer: [{
type: ViewChild,
args: ['pagingContainer', { read: ViewContainerRef, static: true }]
}], metadataGathererChild: [{
type: ContentChild,
args: [METADATA_GATHERER]
}] } });
//# sourceMappingURL=grid.component.js.map