1 import {Component, Input, Output, OnInit, AfterViewInit, EventEmitter,
2 OnDestroy, HostListener, ViewEncapsulation, QueryList, ViewChildren} from '@angular/core';
3 import {Subscription} from 'rxjs';
4 import {IdlService} from '@eg/core/idl.service';
5 import {OrgService} from '@eg/core/org.service';
6 import {ServerStoreService} from '@eg/core/server-store.service';
7 import {FormatService} from '@eg/core/format.service';
8 import {GridContext, GridColumn, GridDataSource, GridRowFlairEntry} from './grid';
9 import {GridFilterControlComponent} from './grid-filter-control.component';
12 * Main grid entry point.
17 templateUrl: './grid.component.html',
18 styleUrls: ['grid.component.css'],
19 // share grid css globally once imported so all grid component CSS
20 // can live in grid.component.css and to avoid multiple copies of
21 // the CSS when multiple grids are displayed.
22 encapsulation: ViewEncapsulation.None
25 export class GridComponent implements OnInit, AfterViewInit, OnDestroy {
27 // Source of row data.
28 @Input() dataSource: GridDataSource;
30 // IDL class for auto-generation of columns
31 @Input() idlClass: string;
33 // True if any columns are sortable
34 @Input() sortable: boolean;
36 // True if the grid supports sorting of multiple columns at once
37 @Input() multiSortable: boolean;
39 // If true, grid sort requests only operate on data that
40 // already exists in the grid data source -- no row fetching.
41 // The assumption is all data is already available.
42 @Input() useLocalSort: boolean;
44 // Storage persist key / per-grid-type unique identifier
45 // The value is prefixed with 'eg.grid.'
47 // If persistKey is set to "disabled", or does not exist,
48 // the grid will not display a Save button to the user
49 @Input() persistKey: string;
51 @Input() disableSelect: boolean;
53 // Prevent selection of multiple rows
54 @Input() disableMultiSelect: boolean;
56 // Show an extra column in the grid where the caller can apply
57 // row-specific flair (material icons).
58 @Input() rowFlairIsEnabled: boolean;
60 // Returns a material icon name to display in the flar column
61 // (if enabled) for the given row.
62 @Input() rowFlairCallback: (row: any) => GridRowFlairEntry;
64 // Returns a space-separated list of CSS class names to apply to
66 @Input() rowClassCallback: (row: any) => string;
68 // Returns a space-separated list of CSS class names to apply to
69 // a given cell or all cells in a column.
70 @Input() cellClassCallback: (row: any, col: GridColumn) => string;
72 // comma-separated list of fields to show by default.
73 // This field takes precedence over hideFields.
74 // When a value is applied, any field not in this list will
76 @Input() showFields: string;
78 // comma-separated list of fields to hide.
79 // This does not imply all other fields should be visible, only that
80 // the selected fields will be hidden.
81 @Input() hideFields: string;
83 // When true, only display columns that are declared in the markup
84 // and leave all auto-generated fields hidden.
85 @Input() showDeclaredFieldsOnly: boolean;
87 // Allow the caller to jump directly to a specific page of
89 @Input() pageOffset: number;
90 // Pass in a default page size. May be overridden by settings.
91 @Input() pageSize: number;
93 // If true and an idlClass is specificed, the grid assumes
94 // datatype=link fields that link to classes which define a selector
95 // are fleshed with the linked object. And, instead of displaying
96 // the raw field value, displays the selector value from the linked
97 // object. The caller is responsible for fleshing the appropriate
98 // fields in the GridDataSource getRows handler.
100 // This only applies to auto-generated columns.
102 // For example, idlClass="aou" and field="ou_type", the display
103 // value will be ou_type().name() since "name" is the selector
104 // field on the "aout" class.
105 @Input() showLinkSelectors: boolean;
107 @Input() disablePaging: boolean;
111 // filterable: true if the result filtering controls
112 // should be displayed
113 @Input() filterable: boolean;
115 // sticky grid header
117 // stickyHeader: true of the grid header should be
118 // "sticky", i.e., remain visible if if the table is long
119 // and the user has scrolled far enough that the header
120 // would go out of view
121 @Input() stickyHeader: boolean;
123 context: GridContext;
125 // These events are emitted from our grid-body component.
126 // They are defined here for ease of access to the caller.
127 @Output() onRowActivate: EventEmitter<any>;
128 @Output() onRowClick: EventEmitter<any>;
131 private idl: IdlService,
132 private org: OrgService,
133 private store: ServerStoreService,
134 private format: FormatService
137 new GridContext(this.idl, this.org, this.store, this.format);
138 this.onRowActivate = new EventEmitter<any>();
139 this.onRowClick = new EventEmitter<any>();
144 if (!this.dataSource) {
145 throw new Error('<eg-grid/> requires a [dataSource]');
148 this.context.idlClass = this.idlClass;
149 this.context.dataSource = this.dataSource;
150 this.context.persistKey = this.persistKey;
151 this.context.isSortable = this.sortable === true;
152 this.context.isFilterable = this.filterable === true;
153 this.context.stickyGridHeader = this.stickyHeader === true;
154 this.context.isMultiSortable = this.multiSortable === true;
155 this.context.useLocalSort = this.useLocalSort === true;
156 this.context.disableSelect = this.disableSelect === true;
157 this.context.showLinkSelectors = this.showLinkSelectors === true;
158 this.context.disableMultiSelect = this.disableMultiSelect === true;
159 this.context.rowFlairIsEnabled = this.rowFlairIsEnabled === true;
160 this.context.showDeclaredFieldsOnly = this.showDeclaredFieldsOnly;
161 this.context.rowFlairCallback = this.rowFlairCallback;
162 this.context.disablePaging = this.disablePaging === true;
163 if (this.showFields) {
164 this.context.defaultVisibleFields = this.showFields.split(',');
166 if (this.hideFields) {
167 this.context.defaultHiddenFields = this.hideFields.split(',');
170 if (this.pageOffset) {
171 this.context.pager.offset = this.pageOffset;
175 this.context.pager.limit = this.pageSize;
178 // TS doesn't seem to like: let foo = bar || () => '';
179 this.context.rowClassCallback =
180 this.rowClassCallback || function () { return ''; };
181 this.context.cellClassCallback =
182 this.cellClassCallback || function() { return ''; };
188 this.context.initData();
192 this.context.destroy();
196 this.context.reload();
198 reloadSansPagerReset() {
199 this.context.reloadSansPagerReset();