ag-grid
Version:
Advanced Data Grid / Data Table supporting Javascript / React / AngularJS / Web Components
130 lines (105 loc) • 5.8 kB
text/typescript
import {Component} from "../widgets/component";
import {RowNode} from "../entities/rowNode";
import {Utils as _} from '../utils';
import {Autowired} from "../context/context";
import {GridOptionsWrapper} from "../gridOptionsWrapper";
import {Column} from "../entities/column";
import {Events} from "../events";
import {EventService} from "../eventService";
import {GridApi} from "../gridApi";
import {ColumnApi} from "../columnController/columnApi";
import {IsRowSelectable} from "../entities/gridOptions";
export class CheckboxSelectionComponent extends Component {
private gridOptionsWrapper: GridOptionsWrapper;
private eventService: EventService;
private gridApi: GridApi;
private columnApi: ColumnApi;
private eCheckedIcon: HTMLElement;
private eUncheckedIcon: HTMLElement;
private eIndeterminateIcon: HTMLElement;
private rowNode: RowNode;
private column: Column;
private isRowSelectableFunc: IsRowSelectable;
constructor() {
super(`<span class="ag-selection-checkbox"/>`);
}
private createAndAddIcons(): void {
this.eCheckedIcon = _.createIconNoSpan('checkboxChecked', this.gridOptionsWrapper, this.column);
this.eUncheckedIcon = _.createIconNoSpan('checkboxUnchecked', this.gridOptionsWrapper, this.column);
this.eIndeterminateIcon = _.createIconNoSpan('checkboxIndeterminate', this.gridOptionsWrapper, this.column);
let element = this.getGui();
element.appendChild(this.eCheckedIcon);
element.appendChild(this.eUncheckedIcon);
element.appendChild(this.eIndeterminateIcon);
}
private onDataChanged(): void {
// when rows are loaded for the second time, this can impact the selection, as a row
// could be loaded as already selected (if user scrolls down, and then up again).
this.onSelectionChanged();
}
private onSelectableChanged(): void {
this.showOrHideSelect();
}
private onSelectionChanged(): void {
let state = this.rowNode.isSelected();
_.setVisible(this.eCheckedIcon, state === true);
_.setVisible(this.eUncheckedIcon, state === false);
_.setVisible(this.eIndeterminateIcon, typeof state !== 'boolean');
}
private onCheckedClicked(): number {
let groupSelectsFiltered = this.gridOptionsWrapper.isGroupSelectsFiltered();
let updatedCount = this.rowNode.setSelectedParams({newValue: false, groupSelectsFiltered: groupSelectsFiltered});
return updatedCount;
}
private onUncheckedClicked(event: MouseEvent): number {
let groupSelectsFiltered = this.gridOptionsWrapper.isGroupSelectsFiltered();
let updatedCount = this.rowNode.setSelectedParams({newValue: true, rangeSelect: event.shiftKey, groupSelectsFiltered: groupSelectsFiltered});
return updatedCount;
}
private onIndeterminateClicked(event: MouseEvent): void {
let result = this.onUncheckedClicked(event);
if (result===0) {
this.onCheckedClicked();
}
}
public init(params: any): void {
this.rowNode = params.rowNode;
this.column = params.column;
this.createAndAddIcons();
this.onSelectionChanged();
// we don't want the row clicked event to fire when selecting the checkbox, otherwise the row
// would possibly get selected twice
this.addGuiEventListener('click', event => _.stopPropagationForAgGrid(event) );
// likewise we don't want double click on this icon to open a group
this.addGuiEventListener('dblclick', event => _.stopPropagationForAgGrid(event) );
this.addDestroyableEventListener(this.eCheckedIcon, 'click', this.onCheckedClicked.bind(this));
this.addDestroyableEventListener(this.eUncheckedIcon, 'click', this.onUncheckedClicked.bind(this));
this.addDestroyableEventListener(this.eIndeterminateIcon, 'click', this.onIndeterminateClicked.bind(this));
this.addDestroyableEventListener(this.rowNode, RowNode.EVENT_ROW_SELECTED, this.onSelectionChanged.bind(this));
this.addDestroyableEventListener(this.rowNode, RowNode.EVENT_DATA_CHANGED, this.onDataChanged.bind(this));
this.addDestroyableEventListener(this.rowNode, RowNode.EVENT_SELECTABLE_CHANGED, this.onSelectableChanged.bind(this));
this.isRowSelectableFunc = this.gridOptionsWrapper.getIsRowSelectableFunc();
let checkboxVisibleIsDynamic = this.isRowSelectableFunc || this.checkboxCallbackExists();
if (checkboxVisibleIsDynamic) {
this.addDestroyableEventListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.showOrHideSelect.bind(this));
this.showOrHideSelect();
}
}
private showOrHideSelect(): void {
// if the isRowSelectable() is not provided the row node is selectable by default
let selectable = this.rowNode.selectable;
// checkboxSelection callback is deemed a legacy solution however we will still consider it's result.
// If selectable, then also check the colDef callback. if not selectable, this it short circuits - no need
// to call the colDef callback.
if (selectable && this.checkboxCallbackExists()) {
selectable = this.column.isCellCheckboxSelection(this.rowNode);
}
// show checkbox if both conditions are true
this.setVisible(selectable);
}
private checkboxCallbackExists(): boolean {
// column will be missing if groupUseEntireRow=true
let colDef = this.column ? this.column.getColDef() : null;
return colDef && typeof colDef.checkboxSelection === 'function';
}
}