@progress/kendo-angular-grid
Version:
Kendo UI Grid for Angular - high performance data grid with paging, filtering, virtualization, CRUD, and more.
394 lines (387 loc) • 22.3 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import { Component, HostBinding, Input, Inject, Optional, TemplateRef } from '@angular/core';
import { EditService } from '../editing/edit.service';
import { isSpanColumn, isCheckboxColumn, isRowReorderColumn } from '../columns/column-base';
import { CommandColumnComponent } from '../columns/command-column.component';
import { isColumnComponent } from '../columns/column.component';
import { columnsToRender } from "../columns/column-common";
import { ReactiveFormsModule } from '@angular/forms';
import { isPresent, isNullOrEmptyString, extractFormat } from '../utils';
import { CELL_CONTEXT } from './common/cell-context';
import { IdService } from '../common/id.service';
import { reorderIcon } from '@progress/kendo-svg-icons';
import { ContextService } from '../common/provider.service';
import { FieldAccessorPipe } from './common/field-accessor.pipe';
import { IconWrapperComponent } from '@progress/kendo-angular-icons';
import { SelectionCheckboxDirective } from '../selection/selection-checkbox.directive';
import { FocusableDirective } from '../navigation/focusable.directive';
import { NgSwitch, NgSwitchCase, NgIf, NgTemplateOutlet, NgFor, NgSwitchDefault } from '@angular/common';
import { CheckBoxComponent, NumericTextBoxComponent, TextBoxComponent } from '@progress/kendo-angular-inputs';
import { DatePickerComponent } from '@progress/kendo-angular-dateinputs';
import * as i0 from "@angular/core";
import * as i1 from "../editing/edit.service";
import * as i2 from "../common/id.service";
import * as i3 from "../common/provider.service";
import * as i4 from "@angular/forms";
/**
* @hidden
*/
export class CellComponent {
editService;
idService;
ctx;
cellContext;
get commandCellClass() {
return this.isCommand(this.column);
}
get dragHandleCellClass() {
return isRowReorderColumn(this.column);
}
get dragRowHandleLabel() {
return isRowReorderColumn(this.column) ? this.ctx.localization.get('dragRowHandleLabel') : undefined;
}
column;
columnIndex;
isNew = false;
isLoading = false;
isVirtual = false;
loadingTemplate;
set rowIndex(index) {
this._rowIndex = index;
this.updateCellContext();
}
get rowIndex() {
return this._rowIndex;
}
dataItem;
reorderIcon = reorderIcon;
get isEdited() {
if (!(this.editService.isEditing() || this.isNew) || !this.isColumnEditable) {
return false;
}
const editContext = this.editService.columnContext(this.rowIndex, this.column);
return this.isFieldEditable(editContext, this.column);
}
get showLoading() {
return this.isVirtual && this.isLoading;
}
get formGroup() {
return this.editService.context(this.rowIndex).group;
}
get templateContext() {
return this._templateContext;
}
get editTemplateContext() {
this._editTemplateContext.$implicit = this.formGroup;
this._editTemplateContext.isNew = this.isNew;
this._editTemplateContext.column = this.column;
this._editTemplateContext.dataItem = this.dataItem;
this._editTemplateContext.formGroup = this.formGroup;
this._editTemplateContext.rowIndex = this.rowIndex;
return this._editTemplateContext;
}
get rowReorderTemplateContext() {
this._rowReorderTemplateContext.$implicit = this.dataItem;
this._rowReorderTemplateContext.columnIndex = this.columnIndex;
this._rowReorderTemplateContext.rowIndex = this.rowIndex;
return this._rowReorderTemplateContext;
}
get format() {
if (isColumnComponent(this.column) && !isNullOrEmptyString(this.column.format)) {
return extractFormat(this.column.format);
}
return undefined;
}
get isBoundColumn() {
return this.column.field && !this.column.templateRef;
}
get isCheckboxColumn() {
return isCheckboxColumn(this.column) && !this.column.templateRef;
}
get selectionCheckboxId() {
return this.idService.selectionCheckboxId(this.rowIndex);
}
get selectionCheckboxLabel() {
return this.ctx.localization.get('selectionCheckboxLabel');
}
get isSpanColumn() {
return isSpanColumn(this.column) && !this.column.templateRef;
}
get childColumns() {
return columnsToRender([this.column]);
}
get isRowReorderColumn() {
return isRowReorderColumn(this.column) && !this.column.templateRef;
}
get isRowSelectable() {
return this.column.rowSelectable(this._rowIndex);
}
_rowIndex;
get isColumnEditable() {
if (!this.column || this.isCommand(this.column)) {
return false;
}
return this.column.editable !== false;
}
_templateContext = {};
_editTemplateContext = {};
_rowReorderTemplateContext = {};
constructor(editService, idService, ctx, cellContext) {
this.editService = editService;
this.idService = idService;
this.ctx = ctx;
this.cellContext = cellContext;
}
ngDoCheck() {
this.updateCellContext();
}
ngOnChanges() {
this.updateTemplateContext();
}
ngAfterContentChecked() {
this.updateTemplateContext();
}
isCommand(column) {
return column instanceof CommandColumnComponent;
}
isFieldEditable(editContext, column) {
if (!isPresent(editContext)) {
return false;
}
if (isPresent(column.editTemplate)) {
return true;
}
return isPresent(editContext.group) && isPresent(editContext.group.get(column.field));
}
updateCellContext() {
if (this.cellContext) {
this.cellContext.rowIndex = this._rowIndex;
}
}
updateTemplateContext() {
if (!this.column.templateRef) {
return;
}
const context = this._templateContext;
context.isNew = this.isNew;
context.column = this.column;
context.dataItem = this.dataItem;
context.rowIndex = this.rowIndex;
context.columnIndex = this.columnIndex;
context.$implicit = this.dataItem;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellComponent, deps: [{ token: i1.EditService }, { token: i2.IdService }, { token: i3.ContextService }, { token: CELL_CONTEXT, optional: true }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: CellComponent, isStandalone: true, selector: "[kendoGridCell]", inputs: { column: "column", columnIndex: "columnIndex", isNew: "isNew", isLoading: "isLoading", isVirtual: "isVirtual", loadingTemplate: "loadingTemplate", rowIndex: "rowIndex", dataItem: "dataItem" }, host: { properties: { "class.k-command-cell": "this.commandCellClass", "class.k-drag-cell": "this.dragHandleCellClass", "class.k-touch-action-none": "this.dragHandleCellClass", "attr.aria-label": "this.dragRowHandleLabel" } }, usesOnChanges: true, ngImport: i0, template: `
<ng-container [ngSwitch]="isEdited">
<ng-container *ngSwitchCase="false">
<ng-container *ngIf="!showLoading; else loading">
<ng-template *ngIf="column.templateRef"
[ngTemplateOutlet]="column.templateRef"
[ngTemplateOutletContext]="templateContext">
</ng-template>
<ng-container *ngIf="isSpanColumn">
<ng-container *ngFor="let childColumn of childColumns">
{{ dataItem | valueOf: childColumn.field: childColumn.format}}
</ng-container>
</ng-container>
<ng-container *ngIf="isBoundColumn">{{ dataItem | valueOf: column.field: column.format}}</ng-container>
<ng-container *ngIf="isCheckboxColumn && !isNew">
<ng-container *ngIf="isRowSelectable; else nonSelectableRow">
<kendo-checkbox
[kendoGridSelectionCheckbox]="rowIndex"
[attr.id]="selectionCheckboxId"
[inputAttributes]="{'aria-label': selectionCheckboxLabel}">
</kendo-checkbox>
</ng-container>
<ng-template #nonSelectableRow>
<kendo-checkbox *ngIf="column.showDisabledCheckbox"
[kendoGridSelectionCheckbox]="rowIndex"
[attr.id]="selectionCheckboxId"
[inputAttributes]="{'aria-label': selectionCheckboxLabel}"
[disabled]="true"
></kendo-checkbox>
</ng-template>
</ng-container>
<ng-container *ngIf="isRowReorderColumn && !isNew">
<kendo-icon-wrapper *ngIf="!column.dragHandleTemplate?.first"
name="reorder"
[svgIcon]="reorderIcon">
</kendo-icon-wrapper>
<ng-template *ngIf="column.dragHandleTemplate?.first"
[ngTemplateOutlet]="column.rowDragHandleTemplateRef"
[ngTemplateOutletContext]="rowReorderTemplateContext">
</ng-template>
</ng-container>
</ng-container>
<ng-template #loading>
<ng-template
*ngIf="loadingTemplate"
[ngTemplateOutlet]="loadingTemplate"
[ngTemplateOutletContext]="{$implicit: column}">
</ng-template>
<div *ngIf="!loadingTemplate" class="k-skeleton-text k-skeleton"></div>
</ng-template>
</ng-container>
<ng-container *ngSwitchCase="true">
<ng-template
*ngIf="column.editTemplateRef"
[ngTemplateOutlet]="column.editTemplateRef"
[ngTemplateOutletContext]="editTemplateContext">
</ng-template>
<ng-container [ngSwitch]="column.editor" *ngIf="!column.editTemplateRef">
<kendo-numerictextbox
*ngSwitchCase="'numeric'"
[format]="format"
[formControl]="$any(formGroup.get(column.field))"
kendoGridFocusable
></kendo-numerictextbox>
<kendo-datepicker
*ngSwitchCase="'date'"
[format]="format"
[formControl]="$any(formGroup.get(column.field))"
kendoGridFocusable
></kendo-datepicker>
<kendo-checkbox
*ngSwitchCase="'boolean'"
[formControl]="$any(formGroup.get(column.field))"
kendoGridFocusable
></kendo-checkbox>
<kendo-textbox
*ngSwitchDefault
[formControl]="$any(formGroup.get(column.field))"
kendoGridFocusable
></kendo-textbox>
</ng-container>
</ng-container>
</ng-container>
`, isInline: true, dependencies: [{ kind: "directive", type: NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: FocusableDirective, selector: "[kendoGridFocusable],\n [kendoGridEditCommand],\n [kendoGridRemoveCommand],\n [kendoGridSaveCommand],\n [kendoGridCancelCommand],\n [kendoGridSelectionCheckbox]\n ", inputs: ["kendoGridFocusable"] }, { kind: "directive", type: SelectionCheckboxDirective, selector: "[kendoGridSelectionCheckbox]", inputs: ["kendoGridSelectionCheckbox"] }, { kind: "component", type: IconWrapperComponent, selector: "kendo-icon-wrapper", inputs: ["name", "svgIcon", "innerCssClass", "customFontClass", "size"], exportAs: ["kendoIconWrapper"] }, { kind: "component", type: NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "component", type: DatePickerComponent, selector: "kendo-datepicker", inputs: ["focusableId", "cellTemplate", "clearButton", "inputAttributes", "monthCellTemplate", "yearCellTemplate", "decadeCellTemplate", "centuryCellTemplate", "weekNumberTemplate", "headerTitleTemplate", "headerTemplate", "footerTemplate", "footer", "navigationItemTemplate", "weekDaysFormat", "showOtherMonthDays", "activeView", "bottomView", "topView", "calendarType", "animateCalendarNavigation", "disabled", "readonly", "readOnlyInput", "popupSettings", "navigation", "min", "max", "incompleteDateValidation", "autoCorrectParts", "autoSwitchParts", "autoSwitchKeys", "enableMouseWheel", "allowCaretMode", "autoFill", "focusedDate", "value", "format", "twoDigitYearMax", "formatPlaceholder", "placeholder", "tabindex", "tabIndex", "disabledDates", "title", "subtitle", "rangeValidation", "disabledDatesValidation", "weekNumber", "size", "rounded", "fillMode", "adaptiveMode"], outputs: ["valueChange", "focus", "blur", "open", "close", "escape"], exportAs: ["kendo-datepicker"] }, { kind: "directive", type: NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "pipe", type: FieldAccessorPipe, name: "valueOf" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: CheckBoxComponent, selector: "kendo-checkbox", inputs: ["checkedState", "rounded"], outputs: ["checkedStateChange"], exportAs: ["kendoCheckBox"] }, { kind: "component", type: TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CellComponent, decorators: [{
type: Component,
args: [{
selector: '[kendoGridCell]',
template: `
<ng-container [ngSwitch]="isEdited">
<ng-container *ngSwitchCase="false">
<ng-container *ngIf="!showLoading; else loading">
<ng-template *ngIf="column.templateRef"
[ngTemplateOutlet]="column.templateRef"
[ngTemplateOutletContext]="templateContext">
</ng-template>
<ng-container *ngIf="isSpanColumn">
<ng-container *ngFor="let childColumn of childColumns">
{{ dataItem | valueOf: childColumn.field: childColumn.format}}
</ng-container>
</ng-container>
<ng-container *ngIf="isBoundColumn">{{ dataItem | valueOf: column.field: column.format}}</ng-container>
<ng-container *ngIf="isCheckboxColumn && !isNew">
<ng-container *ngIf="isRowSelectable; else nonSelectableRow">
<kendo-checkbox
[kendoGridSelectionCheckbox]="rowIndex"
[attr.id]="selectionCheckboxId"
[inputAttributes]="{'aria-label': selectionCheckboxLabel}">
</kendo-checkbox>
</ng-container>
<ng-template #nonSelectableRow>
<kendo-checkbox *ngIf="column.showDisabledCheckbox"
[kendoGridSelectionCheckbox]="rowIndex"
[attr.id]="selectionCheckboxId"
[inputAttributes]="{'aria-label': selectionCheckboxLabel}"
[disabled]="true"
></kendo-checkbox>
</ng-template>
</ng-container>
<ng-container *ngIf="isRowReorderColumn && !isNew">
<kendo-icon-wrapper *ngIf="!column.dragHandleTemplate?.first"
name="reorder"
[svgIcon]="reorderIcon">
</kendo-icon-wrapper>
<ng-template *ngIf="column.dragHandleTemplate?.first"
[ngTemplateOutlet]="column.rowDragHandleTemplateRef"
[ngTemplateOutletContext]="rowReorderTemplateContext">
</ng-template>
</ng-container>
</ng-container>
<ng-template #loading>
<ng-template
*ngIf="loadingTemplate"
[ngTemplateOutlet]="loadingTemplate"
[ngTemplateOutletContext]="{$implicit: column}">
</ng-template>
<div *ngIf="!loadingTemplate" class="k-skeleton-text k-skeleton"></div>
</ng-template>
</ng-container>
<ng-container *ngSwitchCase="true">
<ng-template
*ngIf="column.editTemplateRef"
[ngTemplateOutlet]="column.editTemplateRef"
[ngTemplateOutletContext]="editTemplateContext">
</ng-template>
<ng-container [ngSwitch]="column.editor" *ngIf="!column.editTemplateRef">
<kendo-numerictextbox
*ngSwitchCase="'numeric'"
[format]="format"
[formControl]="$any(formGroup.get(column.field))"
kendoGridFocusable
></kendo-numerictextbox>
<kendo-datepicker
*ngSwitchCase="'date'"
[format]="format"
[formControl]="$any(formGroup.get(column.field))"
kendoGridFocusable
></kendo-datepicker>
<kendo-checkbox
*ngSwitchCase="'boolean'"
[formControl]="$any(formGroup.get(column.field))"
kendoGridFocusable
></kendo-checkbox>
<kendo-textbox
*ngSwitchDefault
[formControl]="$any(formGroup.get(column.field))"
kendoGridFocusable
></kendo-textbox>
</ng-container>
</ng-container>
</ng-container>
`,
standalone: true,
imports: [NgSwitch, NgSwitchCase, NgIf, NgTemplateOutlet, NgFor, FocusableDirective, SelectionCheckboxDirective,
IconWrapperComponent, NumericTextBoxComponent, DatePickerComponent, NgSwitchDefault, FieldAccessorPipe, ReactiveFormsModule, CheckBoxComponent, TextBoxComponent]
}]
}], ctorParameters: function () { return [{ type: i1.EditService }, { type: i2.IdService }, { type: i3.ContextService }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [CELL_CONTEXT]
}] }]; }, propDecorators: { commandCellClass: [{
type: HostBinding,
args: ['class.k-command-cell']
}], dragHandleCellClass: [{
type: HostBinding,
args: ['class.k-drag-cell']
}, {
type: HostBinding,
args: ['class.k-touch-action-none']
}], dragRowHandleLabel: [{
type: HostBinding,
args: ['attr.aria-label']
}], column: [{
type: Input
}], columnIndex: [{
type: Input
}], isNew: [{
type: Input
}], isLoading: [{
type: Input
}], isVirtual: [{
type: Input
}], loadingTemplate: [{
type: Input
}], rowIndex: [{
type: Input
}], dataItem: [{
type: Input
}] } });